-
Notifications
You must be signed in to change notification settings - Fork 42
Expand file tree
/
Copy pathimport-translations
More file actions
executable file
·157 lines (128 loc) · 5.25 KB
/
import-translations
File metadata and controls
executable file
·157 lines (128 loc) · 5.25 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
#!/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:]))