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:
Eemeli Aro 2022-03-18 14:36:54 +00:00
parent 3b2e543bf3
commit c3af76718f
8 changed files with 0 additions and 411 deletions

View File

@ -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()

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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