Module:Calc fn name

    From The Document Foundation Wiki

    This module is used in Calc function articles to save translator time. It replaces an English Calc function name with its translation automatically according to the language of the article.

    The Python script used to extract the translated function names is included below (click expand to see it).

    
    #!/usr/bin/env python3
    #
    # Script for extracting translated Calc function names from LibreOffice
    # .po files and outputting a Lua table that can be used in a wiki module.
    # The Lua output depends on https://github.com/SirAnthony/slpp
    # Also outputs a JSON list of English function names sorted from longest
    # to shortest, with single character names omitted. The list is used with
    # a Firefox Greasemonkey script to replace function names with
    # the wiki module invocation.
    
    import json
    import sys
    import slpp
    from pathlib import Path
    
    if len(sys.argv) != 2:
        sys.exit('Please give argument for the location of translations/source/ with trailing slash, example: python function_names_to_json.py /home/user/libreoffice/translations/source/')
    
    translations = sys.argv[1]
    
    if not Path(translations).exists():
        sys.exit('Error: the directory does not exist.')
    
    if not translations.endswith('/'):
        sys.exit('Error: no trailing slash in path.')
    
    functions = {}
    
    class LuaSpaces(slpp.SLPP):
        def __init__(self):
            slpp.SLPP.__init__(self)
            self.tab = '    '
    
    def suffix(fn_name):
        if fn_name in ['CUMIPMT', 'CUMPRINC', 'EFFECT', 'NOMINAL', 'ISEVEN', 'ISODD' ]:
            return '_ADD'
        elif fn_name in ['GCD', 'LCM', 'NETWORKDAYS', 'WEEKNUM']:
            return '_EXCEL2003'
        return ''
    
    with open(translations + 'ab/formula/messages.po', 'r') as m:
        lines = m.readlines()
        for i in range(len(lines)):
            if lines[i].find('formula/inc/core_resource.hrc') >= 0:
                fn_name = lines[i+2].rsplit('"', 2)[1]
                # we want even the error strings, but not the ones that have lowercase letters
                if fn_name.isupper():
                    functions[fn_name] = {}
                i += 3
    
    with open(translations + 'ab/scaddins/messages.po', 'r') as m:
        lines = m.readlines()
        for i in range(len(lines)):
            if lines[i].find('scaddins/inc/strings.hrc') >= 0:
                fn_name = lines[i+2].rsplit('"', 2)[1]
                fn_name += suffix(fn_name)
                functions[fn_name] = {}
                i += 3
    
    fn_names = functions.keys()
    
    basepath = Path(translations)
    for entry in sorted(basepath.iterdir()):
        if entry.is_dir():
            with open(translations + entry.name + '/formula/messages.po', 'r') as m:
                lines = m.readlines()
                for fn_name in fn_names:
                    for i in range(len(lines)):
                        if lines[i].find('msgid "' + fn_name + '"') >= 0:
                            tr_name = lines[i+1].rsplit('"', 2)[1]
                            if len(tr_name) > 0 and tr_name != fn_name:
                                functions[fn_name][entry.name.lower()] = tr_name
            with open(translations + entry.name + '/scaddins/messages.po', 'r') as m:
                lines = m.readlines()
                for fn_name in fn_names:
                    for i in range(len(lines)):
                        if lines[i].find('scaddins/inc/strings.hrc') >= 0 and lines[i+2].find('msgid "' + fn_name + '"') >= 0:
                            add_suffix = suffix(fn_name)
                            fn_name += add_suffix
                            tr_name = lines[i+3].rsplit('"', 2)[1]
                            if len(tr_name) > 0 and tr_name != fn_name:
                                functions[fn_name][entry.name.lower()] = tr_name + add_suffix
    
    names_for_js = [x.replace("?", "\\?") for x in list(fn_names) if len(x)>1]
    names_for_js.sort(key=len, reverse=True)
    
    as_json = json.dumps(names_for_js, indent=4, ensure_ascii=False)
    as_lua = LuaSpaces().encode(functions)
    
    with open('calc_function_names.js', 'w') as f:
        f.write(as_json)
    
    with open('calc_function_name_translations.lua', 'w') as f:
        f.write(as_lua)
    
    

    -- Invoke from a wrapper template like so:
    -- {{#invoke:Calc_fn_name|main}}
    -- Pass arguments to template like so:
    -- {{Calc_fn_name|IF|{{PAGELANGUAGE}}}}
    -- Hopefully in the future we don't have to pass the language argument:
    -- https://phabricator.wikimedia.org/T161976
    local p = {};
    
    local function get_fn_name( frame )
    
        local fn_names = mw.loadData( 'Module:Calc_fn_name/data' )
        local fn_name = frame:getParent().args[1]
        local lang = frame:getParent().args[2]
    
        if not lang or lang == '' then
            return fn_name
        end    
        
        local tr_name = fn_names[fn_name][lang]
        
        if not tr_name or tr_name == '' then
            tr_name = fn_name
        end
    
        -- have to escape # chars or they will be rendered as ordered lists!
        local tr_name_escaped = string.gsub( tr_name, "#", "#" )
    
        return tr_name_escaped
    
    end
    
    function p.main( frame )
        return get_fn_name( frame )
    end
    
    return p