Jump to content

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 + 'en-GB/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 + 'en-GB/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

functions['Err:'] = {}
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 + '/sc/messages.po', 'r') as m:
            lines = m.readlines()
            for i in range(len(lines)):
                if lines[i].find('msgid "Err:"') >= 0:
                    tr_name = lines[i+1].rsplit('"', 2)[1]
                    if len(tr_name) > 0 and tr_name != 'Err:':
                        functions['Err:'][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}}
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 = mw.loadData("Module:PageLang").langcode

    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