blob: aafec151cd2516c9bf3e5eee5a888f18f1f8af6c [file] [log] [blame]
#!/usr/bin/env python3
# Copyright 2019 The ChromiumOS Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Import generated translations from Google's internal Translation Console."""
import glob
import json
import logging
import os
import sys
import nassh # pylint: disable=wrong-import-order
import libdot
import filter_translations # pylint: disable=wrong-import-order
def get_parser():
"""Get a command line parser."""
parser = libdot.ArgumentParser(description=__doc__)
parser.add_argument(
"--skip-git",
dest="run_git",
action="store_false",
default=True,
help="Skip creating a new git commit.",
)
parser.add_argument(
"builddir", help="Input path to the compiled locale messages."
)
parser.add_argument(
"sourcedir",
nargs="?",
default=os.path.join(nassh.DIR, "_locales"),
help="Output path to nassh/_locales/ directory.",
)
return parser
def main(argv):
"""The main func!"""
parser = get_parser()
opts = parser.parse_args(argv)
opts.builddir = os.path.abspath(opts.builddir)
opts.sourcedir = os.path.abspath(opts.sourcedir)
# The english translation is the hand maintained baseline.
with open(os.path.join(opts.sourcedir, "en", "messages.json"), "rb") as fp:
baseline = json.load(fp)
# The translation process normalizes all the ids to lowercase, so do that
# here too to simplify checks later on.
for msgid, msg in sorted(baseline.items()):
libdot.minify_translations.minify_placeholders(msg)
baseline[msgid.lower()] = baseline.pop(msgid)
# Find new translations. Do it here for smoke checking.
new_locales = glob.glob(os.path.join(opts.builddir, "*", "messages.json"))
if not new_locales:
parser.error("builddir doesn't seem to contain any translations")
# Load & clear existing translations.
logging.info("Clearing existing translation files")
old_trans = {}
os.makedirs(opts.sourcedir, exist_ok=True)
for locale in os.listdir(opts.sourcedir):
locale_dir = os.path.join(opts.sourcedir, locale)
path = os.path.join(locale_dir, "messages.json")
try:
with open(path, "rb") as fp:
old_trans[locale] = json.load(fp)
except FileNotFoundError:
# Completely new translations won't exist yet.
pass
# Special case: English messages are our source of truth, so we'd never
# import those from the dump. Do not try to delete the file.
if locale == "en":
continue
libdot.unlink(path)
# Prune empty dirs.
try:
os.rmdir(locale_dir)
except OSError:
pass
def normalize(msg):
"""Hack up the message string.
English translations don't roundtrip. Sometimes the whitespae gets
mangled -- leading, trailing, or inline. Try to reduce it all down
so we can compare it to the original English input.
"""
return msg["message"].replace(" ", "")
# Copy over the new translations, and merge it with existing content.
logging.info("Importing new translation files")
for in_locale in new_locales:
locale = os.path.basename(os.path.dirname(in_locale))
out_locale = os.path.join(opts.sourcedir, locale, "messages.json")
os.makedirs(os.path.dirname(out_locale), exist_ok=True)
# Strip out untranslated strings. This saves space, and we'd rather
# use the older (perhaps stale) translations than the english one.
with open(in_locale, "rb") as fp:
new = json.load(fp)
# Strip translations only used by the CWS.
new.pop("cws_description", None)
new.pop("cws_description_dev", None)
old = old_trans.get(locale, {})
for msgid, msg in sorted(new.items()):
# The conversion process is a bit buggy :(.
msg["message"] = msg["message"].replace(
"chromium- hterm@chromium.org", "chromium-hterm@chromium.org"
)
# The CWS requires manifest strings be in all locales. It should
# fall back to English automatically, but it doesn't.
if msgid == "nassh_product_name":
new.setdefault(msgid, baseline[msgid])
continue
# If we've deleted a message, delete it from the translations too.
if msgid not in baseline:
new.pop(msgid)
continue
if normalize(baseline[msgid]) == normalize(msg):
if msgid in old:
new[msgid] = old[msgid]
else:
new.pop(msgid)
# If we don't have any translations yet, ignore it.
if len(new) <= 1:
continue
filter_translations.reformat(new, output=out_locale)
# Generate git commits automatically.
if opts.run_git:
libdot.run(["git", "checkout", "-f", "en/"], cwd=opts.sourcedir)
libdot.run(["git", "add", "."], cwd=opts.sourcedir)
libdot.run(
["git", "commit", "-m", "nassh: update translations", "."],
cwd=opts.sourcedir,
)
if __name__ == "__main__":
sys.exit(main(sys.argv[1:]))