mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-24 21:31:04 +00:00
Bug 1745905 - Drop extraneous convert_xul_to_fluent script. r=jaws
The in-tree copy of the XUL+DTD -> Fluent migration script was added in bug 1517528. The original [0] has been refactored and updated since then, while the copy here has not been maintained. It should be removed to clarify the situation. Firefox source docs [1] were updated for Bug 1596726 to include a link to the original script. [0]: https://github.com/zbraniecki/convert_xul_to_fluent [1]: https://firefox-source-docs.mozilla.org/l10n/migrations/legacy.html Differential Revision: https://phabricator.services.mozilla.com/D133886
This commit is contained in:
parent
3b2e543bf3
commit
c3af76718f
@ -1,118 +0,0 @@
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
from __future__ import absolute_import
|
||||
from __future__ import print_function
|
||||
from lib.xul import collect_messages
|
||||
from lib.dtd import get_dtds
|
||||
from lib.utils import read_file, write_file
|
||||
from lib.migration import build_migration
|
||||
from lib.fluent import build_ftl
|
||||
import json
|
||||
import argparse
|
||||
import sys
|
||||
|
||||
# import re
|
||||
|
||||
# To run this, you'll need to have lxml installed:
|
||||
# `pip install lxml`
|
||||
|
||||
# default migration directions
|
||||
data = {
|
||||
"migration": "python/l10n/fluent_migrations",
|
||||
"description": "Migrate l10n strings",
|
||||
"prefix": "",
|
||||
}
|
||||
|
||||
|
||||
def parse_inputs():
|
||||
sys_args = sys.argv[1:]
|
||||
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("bug_id", type=str, help="Id number for bug tracking")
|
||||
parser.add_argument(
|
||||
"xul", type=str, help="POSIX path from mozilla-central to the XML to be updated"
|
||||
)
|
||||
parser.add_argument(
|
||||
"ftl",
|
||||
type=str,
|
||||
help="Case sensitive POSIX path from mozilla-central to desired ftl file",
|
||||
)
|
||||
parser.add_argument(
|
||||
"mozilla_central",
|
||||
type=str,
|
||||
help="Case sensitive absolute POSIX path to current mozilla-central repo",
|
||||
)
|
||||
parser.add_argument(
|
||||
"dtd",
|
||||
type=str,
|
||||
help="comma delimited list of case sensitive POSIX dtd file paths",
|
||||
)
|
||||
parser.add_argument("description", type=str, help="string enclosed in quotes")
|
||||
parser.add_argument(
|
||||
"--dry-run", action="store_true", help="Tell if running dry run or not"
|
||||
)
|
||||
parser.add_argument(
|
||||
"--prefix", type=str, help="a keyword string to be added to all l10n ids"
|
||||
)
|
||||
|
||||
parsed_args = parser.parse_args(sys_args)
|
||||
|
||||
data["description"] = parsed_args.description
|
||||
data["bug_id"] = parsed_args.bug_id
|
||||
data["xul"] = parsed_args.xul
|
||||
data["ftl"] = parsed_args.ftl
|
||||
data["mozilla-central"] = parsed_args.mozilla_central
|
||||
data["dtd"] = parsed_args.dtd.split(",")
|
||||
data["dry-run"] = parsed_args.dry_run
|
||||
data["prefix"] = parsed_args.prefix
|
||||
data["recipe"] = "bug_{}_{}.py".format(
|
||||
data["bug_id"], data["xul"].split("/")[-1].split(".")[0]
|
||||
)
|
||||
|
||||
main()
|
||||
|
||||
|
||||
def main():
|
||||
dry_run = data["dry-run"]
|
||||
dtds = get_dtds(data["dtd"], data["mozilla-central"])
|
||||
|
||||
print("======== DTDs ========")
|
||||
print(json.dumps(dtds, sort_keys=True, indent=2))
|
||||
|
||||
s = read_file(data["xul"], data["mozilla-central"])
|
||||
|
||||
print("======== INPUT ========")
|
||||
print(s)
|
||||
|
||||
print("======== OUTPUT ========")
|
||||
(new_xul, messages) = collect_messages(s, data["prefix"])
|
||||
print(new_xul)
|
||||
if not dry_run:
|
||||
write_file(data["xul"], new_xul, data["mozilla-central"])
|
||||
|
||||
print("======== L10N ========")
|
||||
|
||||
print(json.dumps(messages, sort_keys=True, indent=2))
|
||||
|
||||
migration = build_migration(messages, dtds, data)
|
||||
|
||||
print("======== MIGRATION ========")
|
||||
print(migration)
|
||||
recipe_path = "{}/{}".format(data["migration"], data["recipe"])
|
||||
if not dry_run:
|
||||
write_file(recipe_path, migration, data["mozilla-central"])
|
||||
|
||||
ftl = build_ftl(messages, dtds, data)
|
||||
|
||||
print("======== Fluent ========")
|
||||
print(ftl.encode("utf-8"))
|
||||
if not dry_run:
|
||||
write_file(
|
||||
data["ftl"], ftl.encode("utf-8"), data["mozilla-central"], append=True
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
parse_inputs()
|
@ -1,7 +0,0 @@
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
from __future__ import absolute_import
|
||||
|
||||
# from .xul import collect_messages
|
@ -1,28 +0,0 @@
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
from __future__ import absolute_import
|
||||
from io import StringIO
|
||||
from lxml import etree
|
||||
from .utils import read_file
|
||||
|
||||
|
||||
def get_dtds(sources, base_path):
|
||||
entries = {}
|
||||
for source in sources:
|
||||
dtd = get_dtd(source, base_path)
|
||||
for entry in dtd:
|
||||
entries[entry] = {"value": dtd[entry], "file": source}
|
||||
return entries
|
||||
|
||||
|
||||
def get_dtd(dtd_source, base_path):
|
||||
entries = {}
|
||||
|
||||
source = read_file(dtd_source, base_path)
|
||||
|
||||
dtd = etree.DTD(StringIO(source.decode("utf-8")))
|
||||
for entity in dtd.entities():
|
||||
entries[entity.name] = entity.content
|
||||
return entries
|
@ -1,34 +0,0 @@
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
from __future__ import absolute_import
|
||||
from fluent.syntax import ast
|
||||
from fluent.syntax.serializer import FluentSerializer
|
||||
|
||||
|
||||
def get_value_from_dtd(name, dtd):
|
||||
return dtd[name[1:-1]]["value"]
|
||||
|
||||
|
||||
def build_ftl(messages, dtd, data):
|
||||
res = ast.Resource()
|
||||
|
||||
for id_str in messages:
|
||||
msg = messages[id_str]
|
||||
l10n_id = ast.Identifier(id_str)
|
||||
val = None
|
||||
attrs = []
|
||||
if msg["value"]:
|
||||
dtd_val = get_value_from_dtd(msg["value"], dtd)
|
||||
val = ast.Pattern([ast.TextElement(dtd_val)])
|
||||
for attr_name in msg["attrs"]:
|
||||
dtd_val = get_value_from_dtd(msg["attrs"][attr_name], dtd)
|
||||
attr_val = ast.Pattern([ast.TextElement(dtd_val)])
|
||||
attrs.append(ast.Attribute(ast.Identifier(attr_name), attr_val))
|
||||
|
||||
m = ast.Message(l10n_id, val, attrs)
|
||||
res.body.append(m)
|
||||
|
||||
serializer = FluentSerializer()
|
||||
return serializer.serialize(res)
|
@ -1,77 +0,0 @@
|
||||
from __future__ import absolute_import
|
||||
|
||||
|
||||
def to_chrome_path(path):
|
||||
path = path.replace("/locales/en-US", "")
|
||||
if path.startswith("./"):
|
||||
path = path[2:]
|
||||
return path
|
||||
|
||||
|
||||
def get_dtd_path(name, dtds):
|
||||
return dtds[name[1:-1]]["file"]
|
||||
|
||||
|
||||
def get_entity_name(s):
|
||||
return s[1:-1]
|
||||
|
||||
|
||||
def ind(n=0):
|
||||
return " " * 4 * n
|
||||
|
||||
|
||||
def add_copy(dtd, entity_id):
|
||||
result = "{ " + 'COPY("{0}", "{1}")'.format(dtd, entity_id) + " }\n"
|
||||
return result
|
||||
|
||||
|
||||
def make_header():
|
||||
res = "# coding=utf8\n\n"
|
||||
res += "# Any copyright is dedicated to the Public Domain.\n"
|
||||
res += "# http://creativecommons.org/publicdomain/zero/1.0/\n\n"
|
||||
res += "from __future__ import absolute_import\n"
|
||||
res += "import fluent.syntax.ast as FTL\n"
|
||||
res += "from fluent.migrate.helpers import transforms_from\n"
|
||||
res += "from fluent.migrate.helpers import MESSAGE_REFERENCE, "
|
||||
res += "TERM_REFERENCE, VARIABLE_REFERENCE\n"
|
||||
res += "from fluent.migrate import COPY, CONCAT, REPLACE\n"
|
||||
|
||||
return res
|
||||
|
||||
|
||||
def build_migration(messages, dtds, data):
|
||||
res = make_header()
|
||||
desc = "Bug {0} - {1}, part {{index}}.".format(data["bug_id"], data["description"])
|
||||
res += '\n\ndef migrate(ctx):\n """{0}"""\n\n'.format(desc)
|
||||
|
||||
for dtd_path in data["dtd"]:
|
||||
res += "{0}ctx.maybe_add_localization('{1}')\n".format(
|
||||
ind(1), to_chrome_path(dtd_path)
|
||||
)
|
||||
|
||||
res += "\n"
|
||||
res += ind(1) + "ctx.add_transforms(\n"
|
||||
res += ind(2) + "'{0}',\n".format(to_chrome_path(data["ftl"]))
|
||||
res += ind(2) + "'{0}',\n".format(to_chrome_path(data["ftl"]))
|
||||
res += ind(2) + "transforms_from(\n"
|
||||
res += '"""\n'
|
||||
for l10n_id in messages:
|
||||
msg = messages[l10n_id]
|
||||
if not msg["attrs"]:
|
||||
entity = get_entity_name(msg["value"])
|
||||
entity_path = to_chrome_path(get_dtd_path(msg["value"], dtds))
|
||||
res += "{0} = {1}".format(l10n_id, add_copy(entity_path, entity))
|
||||
else:
|
||||
res += "{0} = \n".format(l10n_id)
|
||||
for name in msg["attrs"]:
|
||||
attr = msg["attrs"][name]
|
||||
attr_name = get_entity_name(attr)
|
||||
entity_path = to_chrome_path(get_dtd_path(attr, dtds))
|
||||
res += "{0}.{1} = {2}".format(
|
||||
ind(1), name, add_copy(entity_path, attr_name)
|
||||
)
|
||||
res += '"""\n'
|
||||
res += ind(2) + ")\n"
|
||||
res += ind(1) + ")"
|
||||
|
||||
return res
|
@ -1,23 +0,0 @@
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
from __future__ import absolute_import
|
||||
import os
|
||||
|
||||
|
||||
def read_file(path, base_path=None):
|
||||
if base_path is not None:
|
||||
path = os.path.join(base_path, path)
|
||||
path = path.replace("\\", "/")
|
||||
with open(path) as fptr:
|
||||
return fptr.read()
|
||||
|
||||
|
||||
def write_file(path, text, base_path=None, append=False):
|
||||
if base_path is not None:
|
||||
path = os.path.join(base_path, path)
|
||||
path = path.replace("\\", "/")
|
||||
mode = "a" if append and os.path.exists(path) else "w"
|
||||
with open(path, mode) as text_file:
|
||||
text_file.write(text)
|
@ -1,117 +0,0 @@
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
from __future__ import absolute_import
|
||||
import re
|
||||
import string
|
||||
|
||||
tag_re = r"<([a-z]+[^>/]*)(/?>)([^<]*)(?:</[a-z]+>)?"
|
||||
attr_re = r'\s+([a-z]+)="([\&\;\.a-zA-Z0-9]+)"'
|
||||
prefix = ""
|
||||
|
||||
messages = {}
|
||||
|
||||
|
||||
def is_entity(s):
|
||||
return s.startswith("&") and s.endswith(";")
|
||||
|
||||
|
||||
def convert_camel_case(name):
|
||||
s1 = re.sub("(.)([A-Z][a-z]+)", r"\1-\2", name)
|
||||
return re.sub("([a-z0-9])([A-Z])", r"\1-\2", s1).lower()
|
||||
|
||||
|
||||
def construct_l10n_id(val, attrs):
|
||||
global prefix
|
||||
id = None
|
||||
if val:
|
||||
id = val[1:-1].strip(string.digits)
|
||||
else:
|
||||
core = None
|
||||
for k in attrs:
|
||||
v = attrs[k][1:-1].strip(string.digits).split(".")
|
||||
if not core:
|
||||
if v[-1].lower() == k:
|
||||
core = ".".join(v[:-1])
|
||||
else:
|
||||
core = ".".join(v)
|
||||
if core:
|
||||
id = core
|
||||
id = id.replace(".", "-")
|
||||
id = convert_camel_case(id)
|
||||
if prefix:
|
||||
id = "{}-{}".format(prefix, id)
|
||||
return id
|
||||
|
||||
|
||||
vector = 0
|
||||
is_l10n = False
|
||||
|
||||
|
||||
def get_indent(pre_tag):
|
||||
if "\n" not in pre_tag:
|
||||
return " "
|
||||
last_bl = pre_tag.rindex("\n")
|
||||
indent = 0
|
||||
for ch in pre_tag[last_bl:]:
|
||||
if ch == " ":
|
||||
indent += 1
|
||||
return "\n" + " " * indent
|
||||
|
||||
|
||||
def tagrepl(m):
|
||||
global vector
|
||||
global is_l10n
|
||||
vector = 0
|
||||
|
||||
is_l10n = False
|
||||
l10n_val = None
|
||||
l10n_attrs = {}
|
||||
if is_entity(m.group(3)):
|
||||
is_l10n = True
|
||||
l10n_val = m.group(3)
|
||||
|
||||
def attrrepl(m2):
|
||||
global vector
|
||||
global is_l10n
|
||||
attr_l10n = False
|
||||
if is_entity(m2.group(2)):
|
||||
attr_l10n = True
|
||||
l10n_attrs[m2.group(1)] = m2.group(2)
|
||||
if attr_l10n:
|
||||
is_l10n = True
|
||||
vector = vector + len(m2.group(0))
|
||||
return ""
|
||||
return m2.group(0)
|
||||
|
||||
tag = re.sub(attr_re, attrrepl, m.group(0))
|
||||
if is_l10n:
|
||||
l10n_id = construct_l10n_id(l10n_val, l10n_attrs)
|
||||
messages[l10n_id] = {"value": l10n_val, "attrs": l10n_attrs}
|
||||
indent = get_indent(tag[0 : len(m.group(1)) + 1 - vector])
|
||||
tag = (
|
||||
tag[0 : len(m.group(1)) + 1 - vector]
|
||||
+ indent
|
||||
+ 'data-l10n-id="'
|
||||
+ l10n_id
|
||||
+ '"'
|
||||
+ m.group(2)
|
||||
+ (m.group(3) if not l10n_val else "")
|
||||
+ tag[len(m.group(1)) + 1 + len(m.group(2)) + len(m.group(3)) - vector :]
|
||||
)
|
||||
return tag
|
||||
|
||||
|
||||
def collect_messages(xul_source, in_prefix):
|
||||
global messages
|
||||
global prefix
|
||||
messages = {}
|
||||
prefix = in_prefix
|
||||
|
||||
new_source = re.sub(tag_re, tagrepl, xul_source)
|
||||
return (new_source, messages)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
pass
|
@ -120,13 +120,6 @@ file-whitespace:
|
||||
- parser/htmlparser/tests
|
||||
- parser/html/java/named-character-references.html
|
||||
- python/devtools/migrate-l10n/migrate/main.py
|
||||
- python/l10n/convert_xul_to_fluent/convert.py
|
||||
- python/l10n/convert_xul_to_fluent/lib/__init__.py
|
||||
- python/l10n/convert_xul_to_fluent/lib/dtd.py
|
||||
- python/l10n/convert_xul_to_fluent/lib/fluent.py
|
||||
- python/l10n/convert_xul_to_fluent/lib/migration.py
|
||||
- python/l10n/convert_xul_to_fluent/lib/utils.py
|
||||
- python/l10n/convert_xul_to_fluent/lib/xul.py
|
||||
- testing/mochitest/bisection.py
|
||||
- testing/mozharness/configs/raptor/linux64_config_taskcluster.py
|
||||
- testing/mozharness/configs/talos/linux64_config_taskcluster.py
|
||||
|
Loading…
Reference in New Issue
Block a user