mirror of
https://github.com/saymrwulf/xous-core.git
synced 2026-11-04 04:27:34 +00:00
Added 'fr' translation Added *.json to .gitattributes Signed-off-by: Tom Marble <tmarble@info9.net>
235 lines
9.1 KiB
Python
Executable file
235 lines
9.1 KiB
Python
Executable file
#! /usr/bin/env python3
|
|
|
|
import argparse
|
|
import json
|
|
import sys
|
|
import os
|
|
import os.path
|
|
import pwd
|
|
import re
|
|
|
|
class Main(object):
|
|
|
|
def __init__(self):
|
|
parser = argparse.ArgumentParser(description="Xous i18n Helper")
|
|
parser.add_argument('-v', '--verbose',
|
|
help='Prints details of each action',
|
|
action='store_true', required=False)
|
|
parser.add_argument('-l', '--list-languages',
|
|
help='Lists current translations',
|
|
action='store_true', required=False)
|
|
parser.add_argument('-i', '--list-i18n-files',
|
|
help='Lists i18n files',
|
|
action='store_true', required=False)
|
|
parser.add_argument('-m', '--missing',
|
|
help='Shows missing translations',
|
|
action='store_true', required=False)
|
|
parser.add_argument('-o', '--show-ok',
|
|
help='Shows OK translations',
|
|
action='store_true', required=False)
|
|
parser.add_argument('-n', '--new-lang',
|
|
help='Add support for a new lang',
|
|
required=False)
|
|
parser.add_argument('-f', '--from-lang',
|
|
help='Copy this existing lang for the new lang',
|
|
required=False)
|
|
self.args = parser.parse_args()
|
|
self.args.program = sys.argv[0]
|
|
if self.args.program[0] != '/':
|
|
self.args.program = os.path.join(os.getcwd(), self.args.program)
|
|
self.args.pdir = os.path.normpath(os.path.dirname(self.args.program))
|
|
self.args.xousdir = os.path.normpath(os.path.dirname(self.args.pdir))
|
|
self.args.program = os.path.basename(self.args.program)
|
|
self.errfile = sys.stderr
|
|
# if end of string matches ' *EN*' (or some other lang)
|
|
self.temp_regex = re.compile('^.* \*[a-zA-Z]{2}\*$')
|
|
self.mt_regex = re.compile('^.* \*MT\*$')
|
|
|
|
def out(self, *objects):
|
|
print(*objects)
|
|
|
|
def err(self, *objects):
|
|
print(*objects, file=self.errfile)
|
|
|
|
def verr(self, *objects):
|
|
if self.args.verbose:
|
|
self.err(*objects)
|
|
|
|
def get_languages(self):
|
|
self.verr('-- get languages --')
|
|
# services/root-keys/locales/i18n.json
|
|
root_keys = os.path.join(self.args.xousdir, 'services', 'root-keys', 'locales', 'i18n.json')
|
|
if not os.path.exists(root_keys):
|
|
self.err('cannot find: %s' % root_keys);
|
|
return 1
|
|
# read keys in "rootkeys.backup_key":
|
|
essential = 'rootkeys.backup_key'
|
|
f = open(root_keys,)
|
|
obj = json.load(f)
|
|
self.languages = []
|
|
if essential in obj:
|
|
for key in obj[essential].keys():
|
|
self.languages.append(key)
|
|
f.close()
|
|
return 0
|
|
|
|
def list_languages(self):
|
|
if self.get_languages() != 0:
|
|
return 1
|
|
self.verr('-- list languages --')
|
|
for lang in self.languages:
|
|
self.out(lang)
|
|
return 0
|
|
|
|
def get_i18n_files(self):
|
|
self.verr('-- get i18n files --')
|
|
self.i18n_files = []
|
|
topdirs = ['apps', 'services']
|
|
for top in topdirs:
|
|
topdir = os.path.join(self.args.xousdir, top)
|
|
if os.path.exists(topdir):
|
|
if top == 'apps':
|
|
manifest = os.path.join(topdir, 'manifest.json')
|
|
if os.path.exists(manifest):
|
|
self.i18n_files.append(manifest[len(self.args.xousdir)+1:])
|
|
for thing in os.listdir(topdir):
|
|
thingdir = os.path.join(topdir, thing)
|
|
if os.path.isdir(thingdir):
|
|
i18n_path = os.path.join(thingdir, 'locales', 'i18n.json')
|
|
if os.path.exists(i18n_path):
|
|
self.i18n_files.append(i18n_path[len(self.args.xousdir)+1:])
|
|
return 0
|
|
|
|
def list_i18n_files(self):
|
|
if self.get_i18n_files() != 0:
|
|
return 1
|
|
self.verr('-- list i18n files --')
|
|
for pathname in self.i18n_files:
|
|
self.out(pathname)
|
|
return 0
|
|
|
|
# keys for
|
|
# manifest APP, menu_name, appmenu.APP
|
|
# other TAG
|
|
def show_missing(self, i18n, is_manifest):
|
|
i18n_path = os.path.join(self.args.xousdir, i18n)
|
|
f = open(i18n_path,)
|
|
obj = json.load(f)
|
|
f.close()
|
|
jqpath = None
|
|
translation = None
|
|
for tag in obj.keys():
|
|
if is_manifest:
|
|
appmenu = 'appmenu.' + tag
|
|
jqpath = tag + '.menu_name.' + appmenu
|
|
translation = obj[tag]['menu_name'][appmenu]
|
|
else:
|
|
jqpath = tag
|
|
translation = obj[tag]
|
|
for lang in self.languages:
|
|
lang_path = jqpath + '.' + lang
|
|
status = 'OK'
|
|
if lang in translation:
|
|
t = translation[lang]
|
|
# to print translation
|
|
# print('%s\t%s\t%s' % (i18n, lang_path, t))
|
|
if t == '🔇':
|
|
status = 'MISSING'
|
|
elif self.mt_regex.fullmatch(t):
|
|
status = 'MACHINE_TRANSLATION'
|
|
elif self.temp_regex.fullmatch(t):
|
|
status = 'TEMPORARY'
|
|
else:
|
|
status = 'ABSENT'
|
|
if self.args.show_ok or status != 'OK':
|
|
print('%s\t%s\t%s' % (i18n, lang_path, status))
|
|
return 0
|
|
|
|
def missing(self):
|
|
if self.get_languages() != 0:
|
|
return 1
|
|
if self.get_i18n_files() != 0:
|
|
return 1
|
|
self.verr('-- missing --')
|
|
for i18n in self.i18n_files:
|
|
is_manifest = os.path.basename(i18n) == 'manifest.json'
|
|
if self.show_missing(i18n, is_manifest) != 0:
|
|
return 1
|
|
return 0
|
|
|
|
# keys for
|
|
# manifest APP, menu_name, appmenu.APP
|
|
# other TAG
|
|
def add_new_lang(self, i18n, is_manifest):
|
|
i18n_path = os.path.join(self.args.xousdir, i18n)
|
|
i18n_path_orig = i18n_path + '.orig'
|
|
if not os.path.exists(i18n_path_orig):
|
|
os.rename(i18n_path, i18n_path_orig)
|
|
self.verr('adding "%s" to %s' % (self.args.new_lang, i18n))
|
|
orig_file = open(i18n_path_orig,)
|
|
obj = json.load(orig_file)
|
|
orig_file.close()
|
|
new_file = open(i18n_path,'w')
|
|
translation = None
|
|
for tag in obj.keys():
|
|
if is_manifest:
|
|
appmenu = 'appmenu.' + tag
|
|
translation = obj[tag]['menu_name'][appmenu]
|
|
else:
|
|
translation = obj[tag]
|
|
t_from = translation[self.args.from_lang]
|
|
t_new = t_from
|
|
if t_from != '🔇':
|
|
t_new += self.from_hint
|
|
translation[self.args.new_lang] = t_new
|
|
json.dump(obj, new_file, ensure_ascii=False, check_circular=False,
|
|
sort_keys=True, indent=4)
|
|
new_file.close()
|
|
return 0
|
|
|
|
def new_lang(self):
|
|
if self.get_i18n_files() != 0:
|
|
return 1
|
|
self.from_hint = ' *%s*' % self.args.from_lang.upper()
|
|
self.verr('-- adding new lang "%s" from "%s" by appending "%s" --' % (self.args.new_lang, self.args.from_lang, self.from_hint))
|
|
for i18n in self.i18n_files:
|
|
is_manifest = os.path.basename(i18n) == 'manifest.json'
|
|
if self.add_new_lang(i18n, is_manifest) != 0:
|
|
return 1
|
|
return 0
|
|
|
|
def run(self):
|
|
rc = 0
|
|
if self.args.verbose:
|
|
self.err('verbose mode')
|
|
self.err('xous dir: "%s"' % self.args.xousdir)
|
|
self.err('program dir: "%s"' % self.args.pdir)
|
|
self.err('program: "%s"' % self.args.program)
|
|
self.err('show-ok: "%s"' % self.args.show_ok)
|
|
if self.args.list_languages:
|
|
rc = self.list_languages()
|
|
elif self.args.list_i18n_files:
|
|
rc = self.list_i18n_files()
|
|
elif self.args.missing:
|
|
rc = self.missing()
|
|
elif self.args.new_lang:
|
|
if not self.args.from_lang:
|
|
self.err('error: you must specify both --from-lang en --to-lang fr')
|
|
rc = 1
|
|
else:
|
|
self.get_languages()
|
|
if not self.args.from_lang in self.languages:
|
|
self.err('error: --from-lang %s is not one of the existing langs: %s' % (self.args.from_lang, self.languages))
|
|
rc = 1
|
|
elif self.args.new_lang in self.languages:
|
|
self.err('error: --new-lang %s must not be one of the existing langs: %s' % (self.args.from_lang, self.languages))
|
|
rc = 1
|
|
elif not re.fullmatch('^[a-z-]{2,6}$', self.args.new_lang):
|
|
self.err('error: --new-lang %s is not valid lang' % self.args.new_lang)
|
|
rc = 1
|
|
else:
|
|
rc = self.new_lang()
|
|
return rc
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(Main().run())
|