Pier Angelo Vendrame pushed to branch main at The Tor Project / Applications / tor-browser-build
Commits:
858ee2ee by Henry Wilkes at 2025-02-18T11:35:44+00:00
Bug 41372: Handle branding strings for tor-browser build.
- - - - -
3 changed files:
- projects/firefox/build
- projects/firefox/config
- + projects/firefox/rename-branding-strings.py
Changes:
=====================================
projects/firefox/build
=====================================
@@ -136,15 +136,50 @@ branding_dir=browser/branding/[% c("var/branding_directory_prefix") %]-[% c("var
[% IF c("var/tor-browser") -%]
tar -C "$rootdir" -xf "$rootdir/[% c('input_files_by_name/translation-tor-browser') %]"
+
+ # For the purpose of Weblate, all releases share a single brand.ftl and
+ # brand.properties file per locale in the translations repository.
+ # See tor-browser-build#41372.
+ # In brand.ftl, both `-brand-short-name` and `-brand-full-name` should
+ # differ between releases. As such, they have additional entries in the
+ # translations repository file (Weblate):
+ # -brand-short-name for the stable release.
+ # -brand-short-name_alpha for the alpha release.
+ # -brand-short-name_nightly for the nightly release.
+ # And similarly for -brand-full-name.
+ # For the final build, we only want to keep the string that matches the
+ # built release, and remove its suffix if it has one. So for the stable
+ # release we want to keep -brand-short-name. For the alpha release we want
+ # to keep -brand-short-name_alpha instead, and rename it to be
+ # -brand-short-name.
+ #
+ # As such, we parse the brand.ftl file to rename these strings to keep the
+ # version we want using rename-branding-strings.py.
+ #
+ # We do a similar thing with brandShortName and brandFullName in
+ # brand.properties.
+
+ # Instructions for the script to perform the renames.
+ brand_ftl_renames='{
+ "suffix": "[% c("var/branding_string_suffix") %]",
+ "ids": ["-brand-short-name", "-brand-full-name"]
+ }'
+ brand_properties_renames='{
+ "suffix": "[% c("var/branding_string_suffix") %]",
+ "ids": ["brandShortName", "brandFullName"]
+ }'
+
pushd "$rootdir/translation-tor-browser"
ln -s ja ja-JP-mac
for lang in $supported_locales; do
mv $lang/tor-browser.ftl "$l10ncentral/$lang/toolkit/toolkit/global/"
- # Branding. Currently all releases use the same branding.
+ # Branding.
l10n_branding_dir="$l10ncentral/$lang/$branding_dir/"
mkdir -p "$l10n_branding_dir"
- mv $lang/branding/brand.ftl "$l10n_branding_dir"
- mv $lang/brand.properties "$l10n_branding_dir"
+ # Convert the translations repository branding files into files that work
+ # for this specific build.
+ python3 rename-branding-strings.py $lang/branding/brand.ftl "$brand_ftl_renames" > "$l10n_branding_dir/brand.ftl"
+ python3 rename-branding-strings.py $lang/brand.properties "$brand_properties_renames" > "$l10n_branding_dir/brand.properties"
done
popd
=====================================
projects/firefox/config
=====================================
@@ -54,6 +54,10 @@ var:
rm -Rf "$rezip_tmpdir"
l10n-changesets: '[% exec("git --no-pager show " _ c("git_hash") _ ":browser/locales/l10n-changesets.json", { exec_noco => 1 }) %]'
+ # The branding_string_suffix for the alpha and nightly should be
+ # '_alpha' and '_nightly', matching the "suffix" chosen in the
+ # tor-browser:update-translations.yml file.
+ branding_string_suffix: '_[% c("var/channel") %]'
steps:
src-tarballs:
@@ -94,6 +98,12 @@ targets:
var:
nightly_updates_publish_dir_prefix: basebrowser-
+ release:
+ var:
+ # For the stable release, the suffix is empty.
+ # I.e. we want to select `-brand-short-name` directly.
+ branding_string_suffix: ''
+
nightly:
git_hash: '[% c("var/project-name") %]-[% c("var/firefox_version") %]-[% c("var/browser_branch") %]'
tag_gpg_id: 0
@@ -183,6 +193,8 @@ input_files:
- project: binutils
name: binutils
enable: '[% c("var/linux") && ! c("var/linux-cross") %]'
+ - filename: rename-branding-strings.py
+ enable: '[% c("var/has_l10n") && c("var/tor-browser") %]'
- filename: fix-info-plist.py
enable: '[% c("var/macos") %]'
- filename: nsis-uninstall.patch
=====================================
projects/firefox/rename-branding-strings.py
=====================================
@@ -0,0 +1,96 @@
+import argparse
+import json
+import re
+
+arg_parser = argparse.ArgumentParser(
+ description="Filter a branding file to only include the expected strings"
+)
+arg_parser.add_argument("file", metavar="<file>", help="branding file to process")
+arg_parser.add_argument(
+ "details", metavar="<details>", help="JSON specification for renaming"
+)
+
+args = arg_parser.parse_args()
+details_dict = json.loads(args.details)
+# The suffix we want to search for or remove.
+# Can be empty if we want to select the IDs that have no suffix.
+suffix = details_dict["suffix"]
+# The string IDs we want to rename.
+rename_ids = details_dict["ids"]
+
+
+def parse_ids(string, pattern):
+ """
+ Extract the IDs found in a string.
+
+ :param string: The string to parse.
+ :param pattern: The pattern to capture IDs.
+
+ :yields: A tuple containing a chunk of string and whether the chunk
+ is an ID.
+ """
+ regex = re.compile(pattern, flags=re.MULTILINE + re.ASCII)
+ while True:
+ match = regex.search(string)
+ if not match:
+ yield string, False
+ return
+
+ yield string[: match.start("id")], False
+ yield match.group("id"), True
+ string = string[match.end("id") :]
+
+
+# We want to parse the file and rename the IDs we are interested in.
+# If the ID starts with one of the `rename_ids` but the suffix does
+# not match we append an "_UNUSED" suffix to the ID, to keep it in the output
+# but functionally unused in the final build.
+# Otherwise, if the ID starts with one of the `rename_ids` and the suffix
+# matches we will remove the suffix from the ID, so that it is used in the
+# final build.
+# Everything else found in the file, like entry values, comments and blank
+# lines, will be included in the output as it was.
+#
+# NOTE: This script is constructed to be *independent* of the order in which
+# strings are present in the file. Weblate does not guarantee the order of
+# translated files to use the same ordering as the original en-US file.
+#
+# NOTE: This script should work for all locales. In particular, for Fluent files
+# it needs to be able to handle Fluent Terms that are multi-valued (conditional)
+# and Terms with attributes. Therefore, whilst we could have written a script to
+# *remove* unwanted strings, the parsing logic would have been far more complex
+# to be able to handle all these cases. Hence why we only parse for the Fluent
+# IDs and rename them, which is much simpler.
+with open(args.file, "r") as file:
+ if file.name.endswith(".ftl"):
+ # A Fluent ID is the identifier for a Message or Term, which always
+ # starts on a newline, and will be followed by an "=" character.
+ id_pattern = r"^(?P<id>-?[a-zA-Z][a-zA-Z0-9_-]*) *="
+ elif file.name.endswith(".properties"):
+ # A properties ID can be preceded by whitespace, and can be any
+ # character other than whitespace, ":" or "=". The first character also
+ # cannot be "!" or "#" since this starts a comment. Technically the
+ # Java ".properties" spec allows a ID to include one of these characters
+ # if it is escaped by a "\", but we don't expect or care about such IDs.
+ # The Java spec also has a limited set of whitespace, which excludes
+ # "\v", but we do not expect Weblate or any other serialiser to
+ # insert whitespace beyond "\n", "\r", "\t" or " ".
+ id_pattern = r"^\s*(?P<id>[^!#:=\s][^:=\s]*)"
+ else:
+ raise ValueError(f"Unknown file type {file.name}")
+
+ for part, is_id in parse_ids(file.read(), id_pattern):
+ if is_id:
+ for string_id in rename_ids:
+ if part.startswith(string_id):
+ if part == string_id + suffix:
+ # This string matches the suffix, so we want to use its
+ # value. We adjust the ID to remove the suffix before
+ # printing.
+ part = string_id
+ else:
+ # Keep this entry in the output, but make it unused by
+ # appending to the ID.
+ part += "_UNUSED"
+ break
+ print(part, end="")
View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser-build/-/commit/8…
--
View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser-build/-/commit/8…
You're receiving this email because of your account on gitlab.torproject.org.
Pier Angelo Vendrame pushed to branch tor-browser-128.7.0esr-14.5-1 at The Tor Project / Applications / Tor Browser
Commits:
d9fe34de by Henry Wilkes at 2025-02-18T10:08:15+00:00
fixup! Add CI for Tor Browser
TB 43446: Include alpha and nightly branding in the translation CI.
- - - - -
34838694 by Henry Wilkes at 2025-02-18T10:10:32+00:00
fixup! BB 42305: Add script to combine translation files across versions.
TB 43446: Allow the combine translation script to select some branding
strings from different files.
- - - - -
6fa642ea by Henry Wilkes at 2025-02-18T10:10:33+00:00
fixup! TB 2176: Rebrand Firefox to TorBrowser
TB 43446: Change the branding name for the alpha and nightly releases.
- - - - -
13 changed files:
- .gitlab/ci/jobs/update-translations.yml
- browser/branding/tb-alpha/locales/en-US/brand.ftl
- browser/branding/tb-alpha/locales/en-US/brand.properties
- browser/branding/tb-nightly/locales/en-US/brand.ftl
- browser/branding/tb-nightly/locales/en-US/brand.properties
- browser/branding/tb-release/locales/en-US/brand.ftl
- browser/branding/tb-release/locales/en-US/brand.properties
- tools/base-browser/l10n/combine-translation-versions.py
- tools/base-browser/l10n/combine/combine.py
- tools/base-browser/l10n/combine/tests/test_android.py
- tools/base-browser/l10n/combine/tests/test_dtd.py
- tools/base-browser/l10n/combine/tests/test_fluent.py
- tools/base-browser/l10n/combine/tests/test_properties.py
Changes:
=====================================
.gitlab/ci/jobs/update-translations.yml
=====================================
@@ -17,12 +17,48 @@
{
"name": "brand.ftl",
"where": ["browser/branding/tb-release", "toolkit/torbutton"],
+ "branding": {
+ "versions": [
+ {
+ "name": "Alpha",
+ "suffix": "_alpha",
+ "where": ["browser/branding/tb-alpha"]
+ },
+ {
+ "name": "Nightly",
+ "suffix": "_nightly",
+ "where": ["browser/branding/tb-nightly"]
+ }
+ ],
+ "ids": [
+ "-brand-short-name",
+ "-brand-full-name"
+ ]
+ },
"branch": "tor-browser",
"directory": "branding"
},
{
"name": "brand.properties",
"where": ["browser/branding/tb-release", "toolkit/torbutton"],
+ "branding": {
+ "versions": [
+ {
+ "name": "Alpha",
+ "suffix": "_alpha",
+ "where": ["browser/branding/tb-alpha"]
+ },
+ {
+ "name": "Nightly",
+ "suffix": "_nightly",
+ "where": ["browser/branding/tb-nightly"]
+ }
+ ],
+ "ids": [
+ "brandShortName",
+ "brandFullName"
+ ]
+ },
"branch": "tor-browser"
},
{ "name": "tor-browser.ftl", "branch": "tor-browser" },
=====================================
browser/branding/tb-alpha/locales/en-US/brand.ftl
=====================================
@@ -2,12 +2,16 @@
# that is used by Firefox) to avoid picking up the -brand-short-name values
# that Mozilla includes in the Firefox language packs.
+# The shortened application name for Tor Browser. Shared between versions.
-brand-shorter-name = Tor Browser
--brand-short-name = Tor Browser
--brand-full-name = Tor Browser
+# The default application name for the "alpha" release.
+-brand-short-name = Tor Browser Alpha
+# The full application name for the "alpha" release.
+-brand-full-name = Tor Browser Alpha
# This brand name can be used in messages where the product name needs to
# remain unchanged across different versions (Nightly, Beta, etc.).
-brand-product-name = Tor Browser
+# The name of the Tor Project organisation.
-vendor-short-name = Tor Project
# "Tor" is a trademark names, so should not be translated (not including the quote marks, which can be localized).
# "The Tor Project, Inc." is an organisation name.
=====================================
browser/branding/tb-alpha/locales/en-US/brand.properties
=====================================
@@ -3,6 +3,9 @@
# 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/.
+# The shortened application name for Tor Browser. Shared between versions.
brandShorterName=Tor Browser
-brandShortName=Tor Browser
-brandFullName=Tor Browser
+# The default application name for the "alpha" release.
+brandShortName=Tor Browser Alpha
+# The full application name for the "alpha" release.
+brandFullName=Tor Browser Alpha
=====================================
browser/branding/tb-nightly/locales/en-US/brand.ftl
=====================================
@@ -2,12 +2,16 @@
# that is used by Firefox) to avoid picking up the -brand-short-name values
# that Mozilla includes in the Firefox language packs.
+# The shortened application name for Tor Browser. Shared between versions.
-brand-shorter-name = Tor Browser
--brand-short-name = Tor Browser
--brand-full-name = Tor Browser
+# The default application name for the "nightly" release.
+-brand-short-name = Tor Browser Nightly
+# The full application name for the "nightly" release.
+-brand-full-name = Tor Browser Nightly
# This brand name can be used in messages where the product name needs to
# remain unchanged across different versions (Nightly, Beta, etc.).
-brand-product-name = Tor Browser
+# The name of the Tor Project organisation.
-vendor-short-name = Tor Project
# "Tor" is a trademark names, so should not be translated (not including the quote marks, which can be localized).
# "The Tor Project, Inc." is an organisation name.
=====================================
browser/branding/tb-nightly/locales/en-US/brand.properties
=====================================
@@ -3,6 +3,9 @@
# 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/.
+# The shortened application name for Tor Browser. Shared between versions.
brandShorterName=Tor Browser
-brandShortName=Tor Browser
-brandFullName=Tor Browser
+# The default application name for the "nightly" release.
+brandShortName=Tor Browser Nightly
+# The full application name for the "nightly" release.
+brandFullName=Tor Browser Nightly
=====================================
browser/branding/tb-release/locales/en-US/brand.ftl
=====================================
@@ -2,12 +2,16 @@
# that is used by Firefox) to avoid picking up the -brand-short-name values
# that Mozilla includes in the Firefox language packs.
+# The shortened application name for Tor Browser. Shared between versions.
-brand-shorter-name = Tor Browser
+# The default application name for the stable release.
-brand-short-name = Tor Browser
+# The full application name for the stable release.
-brand-full-name = Tor Browser
# This brand name can be used in messages where the product name needs to
# remain unchanged across different versions (Nightly, Beta, etc.).
-brand-product-name = Tor Browser
+# The name of the Tor Project organisation.
-vendor-short-name = Tor Project
# "Tor" is a trademark names, so should not be translated (not including the quote marks, which can be localized).
# "The Tor Project, Inc." is an organisation name.
=====================================
browser/branding/tb-release/locales/en-US/brand.properties
=====================================
@@ -3,6 +3,9 @@
# 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/.
+# The shortened application name for Tor Browser. Shared between versions.
brandShorterName=Tor Browser
+# The default application name for the stable release.
brandShortName=Tor Browser
+# The full application name for the stable release.
brandFullName=Tor Browser
=====================================
tools/base-browser/l10n/combine-translation-versions.py
=====================================
@@ -306,9 +306,34 @@ for file_dict in json.loads(args.files):
f"{current_file.path} : {stable_file.path}"
)
+ content = None if current_file is None else current_file.content
+
+ # If we have a branding file, we want to also include strings from the other
+ # branding directories that differ from the stable release.
+ # The strings that *differ* per release should be specified in
+ # file_dict["branding"]["ids"]. These strings will be copied from the other
+ # release's branding directory, with an addition suffix added to their ID,
+ # as specified in the version_dict["suffix"].
+ branding = file_dict.get("branding", None)
+ if branding:
+ include_ids = branding["ids"]
+ for version_dict in branding["versions"]:
+ branding_dirs = version_dict.get("where", None)
+ branding_file = current_branch.get_file(name, branding_dirs)
+ if branding_file is None:
+ raise Exception(f"{name} does not exist in {branding_dirs}")
+ content = combine_files(
+ name,
+ content,
+ branding_file.content,
+ f'{version_dict["name"]} Release.',
+ include_ids,
+ version_dict["suffix"],
+ )
+
content = combine_files(
name,
- None if current_file is None else current_file.content,
+ content,
None if stable_file is None else stable_file.content,
f"Will be unused in {current_branch.browser_version_name}!",
)
=====================================
tools/base-browser/l10n/combine/combine.py
=====================================
@@ -14,26 +14,32 @@ if TYPE_CHECKING:
def combine_files(
filename: str,
- new_content: str | None,
- old_content: str | None,
+ primary_content: str | None,
+ alternative_content: str | None,
comment_prefix: str,
+ include_ids: list[str] | None = None,
+ alternative_suffix: str = "",
) -> str | None:
"""Combine two translation files into one to include all strings from both.
- The new content is presented first, and any strings only found in the old
- content are placed at the end with an additional comment.
+ The primary content is presented first, followed by the alternative content
+ at the end with an additional comment.
:param filename: The filename for the file, determines the format.
- :param new_content: The new content for the file, or None if it has been
- deleted.
- :param old_content: The old content for the file, or None if it did not
- exist before.
- :comment_prefix: A comment to include for any strings that are only found in
- the old content. This will be placed before any other comments for the
- string.
+ :param primary_content: The primary content for the file, or None if it does
+ not exist.
+ :param alternative_content: The alternative content for the file, or None if
+ it does not exist.
+ :param comment_prefix: A comment to include for any strings that are
+ appended to the content. This will be placed before any other comments for
+ the string.
+ :param include_ids: String IDs from `alternative_content` we want to
+ include. If this is `None` then we include all strings that do not already
+ have a matching ID in `primary_content`.
+ :param duplicate_suffix: The suffix to apply to the alternative IDs.
:returns: The combined content, or None if both given contents are None.
"""
- if new_content is None and old_content is None:
+ if primary_content is None and alternative_content is None:
return None
# getParser from compare_locale returns the same instance for the same file
@@ -41,7 +47,7 @@ def combine_files(
parser = getParser(filename)
is_android = filename.endswith(".xml")
- if new_content is None:
+ if primary_content is None:
if is_android:
# File was deleted, add some document parts.
content_start = (
@@ -54,7 +60,7 @@ def combine_files(
content_end = ""
existing_keys = []
else:
- parser.readUnicode(new_content)
+ parser.readUnicode(primary_content)
# Start with the same content as the current file.
# For android strings, we want to keep the final "</resources>" until after.
@@ -96,8 +102,8 @@ def combine_files(
entry_iter: Iterable[Any] = ()
# If the file does not exist in the old branch, don't make any additions.
- if old_content is not None:
- parser.readUnicode(old_content)
+ if alternative_content is not None:
+ parser.readUnicode(alternative_content)
entry_iter = parser.walk(only_localizable=False)
for entry in entry_iter:
if isinstance(entry, Junk):
@@ -134,13 +140,19 @@ def combine_files(
if not isinstance(entry, Entity):
raise ValueError(f"Unexpected type: {entry.__class__.__name__}")
- if entry.key in existing_keys:
- # Already included this string in the new translation file.
+ if include_ids is None:
+ # We include the entry if it is not already included.
+ include_entry = entry.key not in existing_keys
+ else:
+ # We include the entry if it is in our list.
+ include_entry = entry.key in include_ids
+ if not include_entry:
# Drop the gathered comments for this Entity.
stacked_comments.clear()
continue
if isinstance(entry, FluentEntity):
+ id_regex = rf"^({re.escape(entry.key)})( *=)"
if fluent_group_comment is not None:
# We have a found GroupComment which has not been included yet.
# All following Entity's will be under its scope, until the next
@@ -149,12 +161,15 @@ def combine_files(
# Added GroupComment, so don't need to add again.
fluent_group_comment = None
elif isinstance(entry, DTDEntity):
+ id_regex = rf"^(\s*<!ENTITY\s*{re.escape(entry.key)})(\s)"
# Include our additional comment before we print the rest for this
# Entity.
additions.append(f"<!-- LOCALIZATION NOTE: {comment_prefix} -->")
elif isinstance(entry, PropertiesEntity):
+ id_regex = rf"^({re.escape(entry.key)})( *=)"
additions.append(f"# {comment_prefix}")
elif isinstance(entry, AndroidEntity):
+ id_regex = rf'^(\s*<string\s[^>]*name="{re.escape(entry.key)})(")'
additions.append(f"<!-- {comment_prefix} -->")
else:
raise ValueError(f"Unexpected Entity type: {entry.__class__.__name__}")
@@ -162,7 +177,17 @@ def combine_files(
# Add any other comment lines that came directly before this Entity.
additions.extend(stacked_comments)
stacked_comments.clear()
- additions.append(entry.all)
+ entry_content = entry.all
+ if alternative_suffix:
+ # NOTE: compare_locales does not allow us to set the entry.key
+ # value. Instead we use a regular expression to append the suffix to
+ # the expected key.
+ entry_content, count = re.subn(
+ id_regex, rf"\1{alternative_suffix}\2", entry_content, flags=re.M
+ )
+ if count != 1:
+ raise ValueError(f"Failed to substitute the ID for {entry.key}")
+ additions.append(entry_content)
content_middle = ""
=====================================
tools/base-browser/l10n/combine/tests/test_android.py
=====================================
@@ -24,6 +24,20 @@ def assert_result(new_content, old_content, expect):
)
+def assert_alternative(content, alternative_content, alternative_ids, expect):
+ content = wrap_in_xml(content)
+ alternative_content = wrap_in_xml(alternative_content)
+ expect = wrap_in_xml(expect)
+ assert expect == combine_files(
+ "test_strings.xml",
+ content,
+ alternative_content,
+ "ALTERNATIVE STRING",
+ alternative_ids,
+ "_alt",
+ )
+
+
def test_combine_empty():
assert_result(None, None, None)
@@ -328,3 +342,74 @@ def test_removed_string_with_comment():
<string name="removed_4">Fourth removed</string>
""",
)
+
+
+def test_alternatives():
+ assert_alternative(
+ """\
+ <string name="string_1">First string</string>
+ """,
+ """\
+ <string name="string_1">Alternative string</string>
+ """,
+ ["string_1"],
+ """\
+ <string name="string_1">First string</string>
+
+ <!-- ALTERNATIVE STRING -->
+ <string name="string_1_alt">Alternative string</string>
+ """,
+ )
+ assert_alternative(
+ """\
+ <!-- Comment 1 -->
+ <string name="string_1">First string</string>
+ <!-- Comment 2 -->
+ <string name="string_2">Second string</string>
+ <string name="string_3">Third string</string>
+ """,
+ """\
+ <string name="string_1">First string</string>
+ <!-- Alt comment -->
+ <string name="string_2">Alternative string</string>
+ <string name="string_3">Third string different</string>
+ <string name="string_4">Other string</string>
+ """,
+ ["string_2"],
+ """\
+ <!-- Comment 1 -->
+ <string name="string_1">First string</string>
+ <!-- Comment 2 -->
+ <string name="string_2">Second string</string>
+ <string name="string_3">Third string</string>
+
+ <!-- ALTERNATIVE STRING -->
+ <!-- Alt comment -->
+ <string name="string_2_alt">Alternative string</string>
+ """,
+ )
+ assert_alternative(
+ """\
+ <string name="string_1">First string</string>
+ <string name="string_2">Second string</string>
+ <string name="string_3">Third string</string>
+ """,
+ """\
+ <string name="string_1">Alternative string</string>
+ <string name="string_3">Third string</string>
+ <!-- comment -->
+ <string name="string_4">Other string</string>
+ """,
+ ["string_1", "string_4"],
+ """\
+ <string name="string_1">First string</string>
+ <string name="string_2">Second string</string>
+ <string name="string_3">Third string</string>
+
+ <!-- ALTERNATIVE STRING -->
+ <string name="string_1_alt">Alternative string</string>
+ <!-- ALTERNATIVE STRING -->
+ <!-- comment -->
+ <string name="string_4_alt">Other string</string>
+ """,
+ )
=====================================
tools/base-browser/l10n/combine/tests/test_dtd.py
=====================================
@@ -16,6 +16,23 @@ def assert_result(new_content, old_content, expect):
)
+def assert_alternative(content, alternative_content, alternative_ids, expect):
+ if content is not None:
+ content = textwrap.dedent(content)
+ if alternative_content is not None:
+ alternative_content = textwrap.dedent(alternative_content)
+ if expect is not None:
+ expect = textwrap.dedent(expect)
+ assert expect == combine_files(
+ "test.dtd",
+ content,
+ alternative_content,
+ "ALTERNATIVE STRING",
+ alternative_ids,
+ ".alt",
+ )
+
+
def test_combine_empty():
assert_result(None, None, None)
@@ -323,3 +340,74 @@ def test_removed_string_with_comment():
<!ENTITY removed.4 "Fourth removed">
""",
)
+
+
+def test_alternatives():
+ assert_alternative(
+ """\
+ <!ENTITY string.1 "First string">
+ """,
+ """\
+ <!ENTITY string.1 "Alternative string">
+ """,
+ ["string.1"],
+ """\
+ <!ENTITY string.1 "First string">
+
+ <!-- LOCALIZATION NOTE: ALTERNATIVE STRING -->
+ <!ENTITY string.1.alt "Alternative string">
+ """,
+ )
+ assert_alternative(
+ """\
+ <!-- LOCALIZATION NOTE: Comment 1 -->
+ <!ENTITY string.1 "First string">
+ <!-- LOCALIZATION NOTE: Comment 2 -->
+ <!ENTITY string.2 "Second string">
+ <!ENTITY string.3 "Third string">
+ """,
+ """\
+ <!ENTITY string.1 "First string">
+ <!-- LOCALIZATION NOTE: Alt comment -->
+ <!ENTITY string.2 "Alternative string">
+ <!ENTITY string.3 "Third string different">
+ <!ENTITY string.4 "Other string">
+ """,
+ ["string.2"],
+ """\
+ <!-- LOCALIZATION NOTE: Comment 1 -->
+ <!ENTITY string.1 "First string">
+ <!-- LOCALIZATION NOTE: Comment 2 -->
+ <!ENTITY string.2 "Second string">
+ <!ENTITY string.3 "Third string">
+
+ <!-- LOCALIZATION NOTE: ALTERNATIVE STRING -->
+ <!-- LOCALIZATION NOTE: Alt comment -->
+ <!ENTITY string.2.alt "Alternative string">
+ """,
+ )
+ assert_alternative(
+ """\
+ <!ENTITY string.1 "First string">
+ <!ENTITY string.2 "Second string">
+ <!ENTITY string.3 "Third string">
+ """,
+ """\
+ <!ENTITY string.1 "Alternative string">
+ <!ENTITY string.3 "Third string">
+ <!-- LOCALIZATION NOTE: comment -->
+ <!ENTITY string.4 "Other string">
+ """,
+ ["string.1", "string.4"],
+ """\
+ <!ENTITY string.1 "First string">
+ <!ENTITY string.2 "Second string">
+ <!ENTITY string.3 "Third string">
+
+ <!-- LOCALIZATION NOTE: ALTERNATIVE STRING -->
+ <!ENTITY string.1.alt "Alternative string">
+ <!-- LOCALIZATION NOTE: ALTERNATIVE STRING -->
+ <!-- LOCALIZATION NOTE: comment -->
+ <!ENTITY string.4.alt "Other string">
+ """,
+ )
=====================================
tools/base-browser/l10n/combine/tests/test_fluent.py
=====================================
@@ -16,6 +16,23 @@ def assert_result(new_content, old_content, expect):
)
+def assert_alternative(content, alternative_content, alternative_ids, expect):
+ if content is not None:
+ content = textwrap.dedent(content)
+ if alternative_content is not None:
+ alternative_content = textwrap.dedent(alternative_content)
+ if expect is not None:
+ expect = textwrap.dedent(expect)
+ assert expect == combine_files(
+ "test.ftl",
+ content,
+ alternative_content,
+ "ALTERNATIVE STRING",
+ alternative_ids,
+ "-alt",
+ )
+
+
def test_combine_empty():
assert_result(None, None, None)
@@ -342,3 +359,119 @@ def test_removed_string_with_comment():
removed-4 = Fourth removed
""",
)
+
+
+def test_alternatives():
+ assert_alternative(
+ """\
+ string-1 = First string
+ .title = hello
+ """,
+ """\
+ string-1 = Alternative string
+ .title = different
+ """,
+ ["string-1"],
+ """\
+ string-1 = First string
+ .title = hello
+
+
+ ## ALTERNATIVE STRING
+
+ string-1-alt = Alternative string
+ .title = different
+ """,
+ )
+ assert_alternative(
+ """\
+ string-1 = First string
+ .title = hello
+ """,
+ """\
+ string-1 = Alternative string
+ """,
+ ["string-1"],
+ """\
+ string-1 = First string
+ .title = hello
+
+
+ ## ALTERNATIVE STRING
+
+ string-1-alt = Alternative string
+ """,
+ )
+ assert_alternative(
+ """\
+ -term-1 = First string
+ """,
+ """\
+ -term-1 = Alternative string
+ """,
+ ["-term-1"],
+ """\
+ -term-1 = First string
+
+
+ ## ALTERNATIVE STRING
+
+ -term-1-alt = Alternative string
+ """,
+ )
+ assert_alternative(
+ """\
+ # Comment 1
+ string-1 = First string
+ # Comment 2
+ string-2 = Second string
+ string-3 = Third string
+ """,
+ """\
+ string-1 = First string
+ # Alt comment
+ string-2 = Alternative string
+ string-3 = Third string different
+ string-4 = Other string
+ """,
+ ["string-2"],
+ """\
+ # Comment 1
+ string-1 = First string
+ # Comment 2
+ string-2 = Second string
+ string-3 = Third string
+
+
+ ## ALTERNATIVE STRING
+
+ # Alt comment
+ string-2-alt = Alternative string
+ """,
+ )
+ assert_alternative(
+ """\
+ string-1 = First string
+ string-2 = Second string
+ string-3 = Third string
+ """,
+ """\
+ string-1 = Alternative string
+ string-3 = Third string
+ # comment
+ -string-4 = Other string
+ """,
+ ["string-1", "-string-4"],
+ """\
+ string-1 = First string
+ string-2 = Second string
+ string-3 = Third string
+
+
+ ## ALTERNATIVE STRING
+
+ string-1-alt = Alternative string
+ # comment
+ -string-4-alt = Other string
+ """,
+ )
=====================================
tools/base-browser/l10n/combine/tests/test_properties.py
=====================================
@@ -16,6 +16,23 @@ def assert_result(new_content, old_content, expect):
)
+def assert_alternative(content, alternative_content, alternative_ids, expect):
+ if content is not None:
+ content = textwrap.dedent(content)
+ if alternative_content is not None:
+ alternative_content = textwrap.dedent(alternative_content)
+ if expect is not None:
+ expect = textwrap.dedent(expect)
+ assert expect == combine_files(
+ "test.properties",
+ content,
+ alternative_content,
+ "ALTERNATIVE STRING",
+ alternative_ids,
+ ".alt",
+ )
+
+
def test_combine_empty():
assert_result(None, None, None)
@@ -320,3 +337,74 @@ def test_removed_string_with_comment():
removed.4 = Fourth removed
""",
)
+
+
+def test_alternatives():
+ assert_alternative(
+ """\
+ string.1 = First string
+ """,
+ """\
+ string.1 = Alternative string
+ """,
+ ["string.1"],
+ """\
+ string.1 = First string
+
+ # ALTERNATIVE STRING
+ string.1.alt = Alternative string
+ """,
+ )
+ assert_alternative(
+ """\
+ # Comment 1
+ string.1 = First string
+ # Comment 2
+ string.2 = Second string
+ string.3 = Third string
+ """,
+ """\
+ string.1 = First string
+ # Alt comment
+ string.2 = Alternative string
+ string.3 = Third string different
+ string.4 = Other string
+ """,
+ ["string.2"],
+ """\
+ # Comment 1
+ string.1 = First string
+ # Comment 2
+ string.2 = Second string
+ string.3 = Third string
+
+ # ALTERNATIVE STRING
+ # Alt comment
+ string.2.alt = Alternative string
+ """,
+ )
+ assert_alternative(
+ """\
+ string.1 = First string
+ string.2 = Second string
+ string.3 = Third string
+ """,
+ """\
+ string.1 = Alternative string
+ string.3 = Third string
+ # comment
+ string.4 = Other string
+ """,
+ ["string.1", "string.4"],
+ """\
+ string.1 = First string
+ string.2 = Second string
+ string.3 = Third string
+
+ # ALTERNATIVE STRING
+ string.1.alt = Alternative string
+ # ALTERNATIVE STRING
+ # comment
+ string.4.alt = Other string
+ """,
+ )
View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/compare/d94603…
--
View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/compare/d94603…
You're receiving this email because of your account on gitlab.torproject.org.
boklm pushed to branch maint-14.0 at The Tor Project / Applications / tor-browser-build
Commits:
119ce448 by Nicolas Vigier at 2025-02-18T12:01:51+01:00
MB 394: Fix package dependency for Debian Trixie
The libgdk-pixbuf2.0-0 package has been removed from Debian Trixie.
We update the symbols file to depend on both libgdk-pixbuf2.0-0 and
libgdk-pixbuf-2.0-0.
https://bugzilla.mozilla.org/show_bug.cgi?id=1933835
- - - - -
1 changed file:
- projects/linux-packages/config
Changes:
=====================================
projects/linux-packages/config
=====================================
@@ -31,6 +31,11 @@ targets:
# some :i386 packages fail to install when /var/lib/dpkg/available
# does not exist, so create it as an empty file
echo > /var/lib/dpkg/available
+ post_pkginst: |
+ # Alter the symbols file for libgdk-pixbuf to handle the transition to libgdk-pixbuf-2.0-0
+ # This is only necessary until we upgrade to something newer than buster.
+ # See mullvad-browser#394 and https://bugzilla.mozilla.org/show_bug.cgi?id=1933835
+ find /var/lib/dpkg/info/ -name libgdk-pixbuf2.0-0*symbols | xargs sed -i "/libgdk-pixbuf2.0-0/s/libgdk-pixbuf2.0-0/libgdk-pixbuf2.0-0 #MINVER# | libgdk-pixbuf-2.0-0/"
arch_deps:
# Packages needed to build the deb package
- dpkg-dev
View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser-build/-/commit/1…
--
View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser-build/-/commit/1…
You're receiving this email because of your account on gitlab.torproject.org.
boklm pushed to branch main at The Tor Project / Applications / tor-browser-build
Commits:
15aae5bd by Nicolas Vigier at 2025-02-17T12:47:15+01:00
MB 394: Fix package dependency for Debian Trixie
The libgdk-pixbuf2.0-0 package has been removed from Debian Trixie.
We update the symbols file to depend on both libgdk-pixbuf2.0-0 and
libgdk-pixbuf-2.0-0.
https://bugzilla.mozilla.org/show_bug.cgi?id=1933835
- - - - -
1 changed file:
- projects/linux-packages/config
Changes:
=====================================
projects/linux-packages/config
=====================================
@@ -32,6 +32,11 @@ targets:
# some foreign-arch packages fail to install when /var/lib/dpkg/available
# does not exist, so create it as an empty file
echo > /var/lib/dpkg/available
+ post_pkginst: |
+ # Alter the symbols file for libgdk-pixbuf to handle the transition to libgdk-pixbuf-2.0-0
+ # This is only necessary until we upgrade to something newer than buster.
+ # See mullvad-browser#394 and https://bugzilla.mozilla.org/show_bug.cgi?id=1933835
+ find /var/lib/dpkg/info/ -name libgdk-pixbuf2.0-0*symbols | xargs sed -i "/libgdk-pixbuf2.0-0/s/libgdk-pixbuf2.0-0/libgdk-pixbuf2.0-0 #MINVER# | libgdk-pixbuf-2.0-0/"
arch_deps:
# Packages needed to build the deb package
- dpkg-dev
@@ -67,6 +72,11 @@ targets:
# some foreign-arch packages fail to install when /var/lib/dpkg/available
# does not exist, so create it as an empty file
echo > /var/lib/dpkg/available
+ post_pkginst: |
+ # Alter the symbols file for libgdk-pixbuf to handle the transition to libgdk-pixbuf-2.0-0
+ # This is only necessary until we upgrade to something newer than buster.
+ # See mullvad-browser#394 and https://bugzilla.mozilla.org/show_bug.cgi?id=1933835
+ find /var/lib/dpkg/info/ -name libgdk-pixbuf2.0-0*symbols | xargs sed -i "/libgdk-pixbuf2.0-0/s/libgdk-pixbuf2.0-0/libgdk-pixbuf2.0-0 #MINVER# | libgdk-pixbuf-2.0-0/"
arch_deps:
# Packages needed to build the deb package
- dpkg-dev
View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser-build/-/commit/1…
--
View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser-build/-/commit/1…
You're receiving this email because of your account on gitlab.torproject.org.
morgan pushed to branch tor-browser-128.7.0esr-14.5-1 at The Tor Project / Applications / Tor Browser
Commits:
e01fb03c by Morgan at 2025-02-13T16:26:45+00:00
fixup! Adding issue and merge request templates
add issue template for mozilla uplifts and tweak MR template to signal to merger an uplift issue should be created after merge
- - - - -
2 changed files:
- + .gitlab/issue_templates/Uplift.md
- .gitlab/merge_request_templates/default.md
Changes:
=====================================
.gitlab/issue_templates/Uplift.md
=====================================
@@ -0,0 +1,19 @@
+<!--
+Title:
+ Uplift tor-browser#12345: Title of Issue
+-->
+
+# Uplift Patchset
+
+## Gitlab Issue(s)
+- tor-browser#12345
+- mullvad-browser#12345
+
+## Upstream Mozilla Issue(s):
+- https://bugzilla.mozilla.org/show_bug.cgi?id=12345
+
+## Notes
+
+<!-- whatever additional info, context, etc that would be helpful for uplifting -->
+
+/label ~"Apps::Type::Uplift"
=====================================
.gitlab/merge_request_templates/default.md
=====================================
@@ -48,6 +48,9 @@
- [ ] **Localization**: typos and other localization changes that should be also in the release branch
- [ ] **Other**: please explain
+### Uplifting
+- [ ] Patchset is a candidate for uplift to Firefox
+
### Issue Tracking
- [ ] Link resolved issues with appropriate [Release Prep issue](https://gitlab.torproject.org/groups/tpo/applications/-/issues/?sort… for changelog generation
View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/commit/e01fb03…
--
View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/commit/e01fb03…
You're receiving this email because of your account on gitlab.torproject.org.