2020-02-24 18:58:07 +01:00
|
|
|
#!/usr/bin/env python3
|
|
|
|
# -*- coding: UTF-8 -*-
|
2020-02-23 08:58:43 +01:00
|
|
|
import os
|
|
|
|
import json
|
|
|
|
import re
|
|
|
|
import sys
|
|
|
|
import polib
|
2020-03-12 10:11:37 +01:00
|
|
|
import shutil
|
2020-02-23 08:58:43 +01:00
|
|
|
from fluent.syntax import parse, serialize
|
2020-02-27 11:37:24 +01:00
|
|
|
from fluent.syntax.ast import Message, TextElement, Identifier, Pattern, Junk
|
2020-02-23 08:58:43 +01:00
|
|
|
|
2020-02-27 11:37:24 +01:00
|
|
|
# extract a translated string from strings.json and insert it into ftl
|
2020-02-23 08:58:43 +01:00
|
|
|
# eg:
|
2020-03-12 08:57:03 +01:00
|
|
|
# $ python extract-po-string.py strings.json /path/to/templates/media-check.ftl delete-unused "Delete Unused Media" ""
|
|
|
|
# $ python extract-po-string.py strings.json /path/to/templates/media-check.ftl delete-unused "%(a)s %(b)s" "%(a)s=$val1,%(b)s=$val2"
|
2020-02-23 08:58:43 +01:00
|
|
|
|
2020-03-12 08:57:03 +01:00
|
|
|
json_filename, ftl_filename, key, msgid_substring, repls = sys.argv[1:]
|
2020-02-23 08:58:43 +01:00
|
|
|
|
|
|
|
# split up replacements
|
|
|
|
replacements = []
|
|
|
|
for repl in repls.split(","):
|
|
|
|
if not repl:
|
|
|
|
continue
|
|
|
|
replacements.append(repl.split("="))
|
|
|
|
|
|
|
|
# add file as prefix to key
|
|
|
|
prefix = os.path.splitext(os.path.basename(ftl_filename))[0]
|
|
|
|
key = f"{prefix}-{key}"
|
|
|
|
|
2020-03-12 08:57:03 +01:00
|
|
|
strings = json.load(open(json_filename, "r"))
|
2020-02-27 11:37:24 +01:00
|
|
|
|
|
|
|
msgids = []
|
|
|
|
if msgid_substring in strings["en"]:
|
|
|
|
# is the ID an exact match?
|
|
|
|
msgids.append(msgid_substring)
|
|
|
|
else:
|
|
|
|
for id in strings["en"].keys():
|
|
|
|
if msgid_substring in id:
|
|
|
|
msgids.append(id)
|
|
|
|
|
|
|
|
msgid = None
|
|
|
|
if len(msgids) == 0:
|
2020-02-23 08:58:43 +01:00
|
|
|
print("no IDs matched")
|
|
|
|
sys.exit(1)
|
2020-02-27 11:37:24 +01:00
|
|
|
elif len(msgids) == 1:
|
|
|
|
msgid = msgids[0]
|
|
|
|
else:
|
|
|
|
for c, id in enumerate(msgids):
|
|
|
|
print(f"* {c}: {id}")
|
|
|
|
msgid = msgids[int(input("number to use? "))]
|
2020-02-23 08:58:43 +01:00
|
|
|
|
2020-03-12 08:57:03 +01:00
|
|
|
|
2020-02-27 11:37:24 +01:00
|
|
|
def transform_entry(entry):
|
|
|
|
if isinstance(entry, str):
|
2020-03-12 08:57:03 +01:00
|
|
|
return transform_string(entry)
|
2020-02-27 11:37:24 +01:00
|
|
|
else:
|
|
|
|
return [transform_string(e) for e in entry]
|
2020-02-23 08:58:43 +01:00
|
|
|
|
2020-03-12 08:57:03 +01:00
|
|
|
|
2020-02-27 11:37:24 +01:00
|
|
|
def transform_string(msg):
|
|
|
|
for (old, new) in replacements:
|
2020-03-12 09:00:59 +01:00
|
|
|
msg = msg.replace(old, f"{new}")
|
2020-02-27 11:37:24 +01:00
|
|
|
# strip leading/trailing whitespace
|
|
|
|
return msg.strip()
|
2020-02-23 08:58:43 +01:00
|
|
|
|
2020-03-12 08:57:03 +01:00
|
|
|
|
2020-02-23 08:58:43 +01:00
|
|
|
to_insert = []
|
2020-02-27 11:37:24 +01:00
|
|
|
for lang in strings.keys():
|
|
|
|
entry = strings[lang].get(msgid)
|
|
|
|
if not entry:
|
|
|
|
continue
|
|
|
|
entry = transform_entry(entry)
|
|
|
|
if entry:
|
|
|
|
print(f"{lang} had translation {entry}")
|
|
|
|
to_insert.append((lang, entry))
|
2020-02-23 08:58:43 +01:00
|
|
|
|
2020-02-27 08:37:40 +01:00
|
|
|
plurals = json.load(open("plurals.json"))
|
2020-02-23 08:58:43 +01:00
|
|
|
|
|
|
|
|
|
|
|
def plural_text(key, lang, translation):
|
|
|
|
lang = re.sub("(_|-).*", "", lang)
|
|
|
|
|
2020-05-05 14:14:39 +02:00
|
|
|
# extract the variable - if there's more than one, use the first one
|
2020-02-23 08:58:43 +01:00
|
|
|
var = re.findall(r"{(\$.*?)}", translation[0])
|
|
|
|
if not len(var) == 1:
|
2020-05-05 14:14:39 +02:00
|
|
|
print("multiple variables found, using first replacement")
|
|
|
|
var = replacements[0][1].replace("{", "").replace("}", "")
|
|
|
|
else:
|
|
|
|
var = var[0]
|
2020-02-23 08:58:43 +01:00
|
|
|
|
|
|
|
buf = f"{key} = {{ {var} ->\n"
|
|
|
|
|
|
|
|
# for each of the plural forms except the last
|
|
|
|
for idx, msg in enumerate(translation[:-1]):
|
|
|
|
plural_form = plurals[lang][idx]
|
|
|
|
buf += f" [{plural_form}] {msg}\n"
|
|
|
|
|
|
|
|
# add the catchall
|
|
|
|
msg = translation[-1]
|
|
|
|
buf += f" *[other] {msg}\n"
|
|
|
|
buf += " }\n"
|
|
|
|
return buf
|
|
|
|
|
|
|
|
|
|
|
|
# add a non-pluralized message. works via fluent.syntax, so can automatically
|
|
|
|
# indent, etc
|
|
|
|
def add_simple_message(fname, key, message):
|
|
|
|
orig = ""
|
|
|
|
if os.path.exists(fname):
|
|
|
|
orig = open(fname).read()
|
|
|
|
|
|
|
|
obj = parse(orig)
|
2020-02-27 11:37:24 +01:00
|
|
|
for ent in obj.body:
|
|
|
|
if isinstance(ent, Junk):
|
|
|
|
raise Exception(f"file had junk! {fname} {ent}")
|
2020-02-23 08:58:43 +01:00
|
|
|
obj.body.append(Message(Identifier(key), Pattern([TextElement(message)])))
|
|
|
|
|
2020-02-27 11:37:24 +01:00
|
|
|
modified = serialize(obj, with_junk=True)
|
|
|
|
# escape leading dots
|
2020-03-12 08:57:03 +01:00
|
|
|
modified = re.sub(r"(?ms)^( +)\.", '\\1{"."}', modified)
|
2020-02-27 11:37:24 +01:00
|
|
|
|
|
|
|
# ensure the resulting serialized file is valid by parsing again
|
|
|
|
obj = parse(modified)
|
|
|
|
for ent in obj.body:
|
|
|
|
if isinstance(ent, Junk):
|
|
|
|
raise Exception(f"introduced junk! {fname} {ent}")
|
|
|
|
|
|
|
|
# it's ok, write it out
|
2020-02-23 08:58:43 +01:00
|
|
|
open(fname, "w").write(modified)
|
|
|
|
|
|
|
|
|
|
|
|
def add_message(fname, key, translation):
|
|
|
|
# simple, non-plural form?
|
|
|
|
if isinstance(translation, str):
|
|
|
|
add_simple_message(fname, key, translation)
|
|
|
|
else:
|
2020-05-05 14:14:39 +02:00
|
|
|
text = plural_text(key, lang, translation)
|
|
|
|
open(fname, "a").write(text)
|
2020-02-23 08:58:43 +01:00
|
|
|
|
|
|
|
print()
|
|
|
|
input("proceed? ctrl+c to abort")
|
|
|
|
|
2020-04-01 09:49:31 +02:00
|
|
|
i18ndir = os.path.join(os.path.dirname(ftl_filename), "..")
|
|
|
|
|
2020-02-27 11:37:24 +01:00
|
|
|
# for each language's translation
|
2020-02-23 08:58:43 +01:00
|
|
|
for lang, translation in to_insert:
|
2020-02-27 11:37:24 +01:00
|
|
|
if lang == "en":
|
|
|
|
# template
|
|
|
|
ftl_path = ftl_filename
|
|
|
|
else:
|
|
|
|
# translation
|
|
|
|
ftl_path = ftl_filename.replace("templates", lang)
|
|
|
|
ftl_dir = os.path.dirname(ftl_path)
|
2020-02-23 08:58:43 +01:00
|
|
|
|
2020-02-27 11:37:24 +01:00
|
|
|
if not os.path.exists(ftl_dir):
|
|
|
|
os.mkdir(ftl_dir)
|
2020-02-23 08:58:43 +01:00
|
|
|
|
|
|
|
add_message(ftl_path, key, translation)
|
|
|
|
|
2020-03-12 10:11:37 +01:00
|
|
|
# copy file from repo into src
|
|
|
|
srcdir = os.path.join(i18ndir, "..", "..")
|
|
|
|
src_filename = os.path.join(srcdir, os.path.basename(ftl_filename))
|
|
|
|
shutil.copy(ftl_filename, src_filename)
|
|
|
|
|
2020-02-23 08:58:43 +01:00
|
|
|
print("done")
|