From 6bf0a5cb5034a7e684dcc3500e841785237ce2dd Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 19:32:43 +0200 Subject: Adding upstream version 1:115.7.0. Signed-off-by: Daniel Baumann --- comm/python/l10n/l10n_clone/l10n_clone.py | 96 ++++ comm/python/l10n/mach_commands.py | 264 ++++++++++ comm/python/l10n/missing_ftl/__init__.py | 59 +++ comm/python/l10n/tb_fluent_migrations/__init__.py | 0 .../bug_1827199_multi_message_view.py | 33 ++ .../bug_1831422_backupKeyPassword.py | 25 + .../bug_1833042_unfied_toolbar_button_style.py | 25 + .../bug_1838109_changeExpiryDlg.py | 27 ++ .../bug_1838770_properties_menu_item.py | 56 +++ .../bug_1703164_calendar_ics_file_dialog.py | 20 + .../bug_1703164_calendar_uri_redirect_dialog.py | 20 + .../completed/bug_1731837_delete_commands.py | 114 +++++ .../bug_1798509_unified_toolbar_customization.py | 52 ++ .../completed/bug_1803705_thread_pane.py | 111 +++++ .../completed/bug_1805746_calendar_view.py | 29 ++ .../bug_1805938_calendar_recurrence_ux.py | 25 + .../bug_1806567_quick_filter_bar_migration.py | 182 +++++++ .../bug_1809312_unified_toolbar_buttons.py | 218 +++++++++ .../bug_1811400_thread_pane_column_picker.py | 79 +++ ...g_1814393_unified_toolbar_customization_tabs.py | 36 ++ .../bug_1814664_unified_toolbar_calendar_items.py | 48 ++ .../bug_1815489_add_back_forward_and_stop.py | 33 ++ ...815605_calendar_context_menu_has_empty_items.py | 52 ++ .../bug_1816532_about_dialog_migration.py | 94 ++++ .../bug_1816593_flexbox_emulation_dialogs.py | 21 + .../completed/bug_1817914_tags_mode.py | 21 + .../completed/bug_1817915_get_new_messages.py | 22 + .../completed/bug_1820700_select_thread.py | 35 ++ .../completed/bug_1823033_activity_indicator.py | 23 + ...act_mode_options_to_folder_mode_context_menu.py | 26 + .../completed/bug_1827891_dnt_prefs_learn_more.py | 21 + .../bug_1828340_aboutdialog_layout_fixes.py | 42 ++ .../completed/bug_1830004_folder_quota.py | 28 ++ .../completed/bug_1834662_cal_enable78.py | 30 ++ .../completed/bug_1834662_extensions_to_fluent.py | 531 +++++++++++++++++++++ comm/python/l10n/tbxchannel/__init__.py | 47 ++ comm/python/l10n/tbxchannel/l10n_merge.py | 26 + .../l10n/tbxchannel/quarantine_to_strings.py | 194 ++++++++ comm/python/l10n/tbxchannel/tb_migration_test.py | 172 +++++++ 39 files changed, 2937 insertions(+) create mode 100644 comm/python/l10n/l10n_clone/l10n_clone.py create mode 100644 comm/python/l10n/mach_commands.py create mode 100644 comm/python/l10n/missing_ftl/__init__.py create mode 100644 comm/python/l10n/tb_fluent_migrations/__init__.py create mode 100644 comm/python/l10n/tb_fluent_migrations/bug_1827199_multi_message_view.py create mode 100644 comm/python/l10n/tb_fluent_migrations/bug_1831422_backupKeyPassword.py create mode 100644 comm/python/l10n/tb_fluent_migrations/bug_1833042_unfied_toolbar_button_style.py create mode 100644 comm/python/l10n/tb_fluent_migrations/bug_1838109_changeExpiryDlg.py create mode 100644 comm/python/l10n/tb_fluent_migrations/bug_1838770_properties_menu_item.py create mode 100644 comm/python/l10n/tb_fluent_migrations/completed/bug_1703164_calendar_ics_file_dialog.py create mode 100644 comm/python/l10n/tb_fluent_migrations/completed/bug_1703164_calendar_uri_redirect_dialog.py create mode 100644 comm/python/l10n/tb_fluent_migrations/completed/bug_1731837_delete_commands.py create mode 100644 comm/python/l10n/tb_fluent_migrations/completed/bug_1798509_unified_toolbar_customization.py create mode 100644 comm/python/l10n/tb_fluent_migrations/completed/bug_1803705_thread_pane.py create mode 100644 comm/python/l10n/tb_fluent_migrations/completed/bug_1805746_calendar_view.py create mode 100644 comm/python/l10n/tb_fluent_migrations/completed/bug_1805938_calendar_recurrence_ux.py create mode 100644 comm/python/l10n/tb_fluent_migrations/completed/bug_1806567_quick_filter_bar_migration.py create mode 100644 comm/python/l10n/tb_fluent_migrations/completed/bug_1809312_unified_toolbar_buttons.py create mode 100644 comm/python/l10n/tb_fluent_migrations/completed/bug_1811400_thread_pane_column_picker.py create mode 100644 comm/python/l10n/tb_fluent_migrations/completed/bug_1814393_unified_toolbar_customization_tabs.py create mode 100644 comm/python/l10n/tb_fluent_migrations/completed/bug_1814664_unified_toolbar_calendar_items.py create mode 100644 comm/python/l10n/tb_fluent_migrations/completed/bug_1815489_add_back_forward_and_stop.py create mode 100644 comm/python/l10n/tb_fluent_migrations/completed/bug_1815605_calendar_context_menu_has_empty_items.py create mode 100644 comm/python/l10n/tb_fluent_migrations/completed/bug_1816532_about_dialog_migration.py create mode 100644 comm/python/l10n/tb_fluent_migrations/completed/bug_1816593_flexbox_emulation_dialogs.py create mode 100644 comm/python/l10n/tb_fluent_migrations/completed/bug_1817914_tags_mode.py create mode 100644 comm/python/l10n/tb_fluent_migrations/completed/bug_1817915_get_new_messages.py create mode 100644 comm/python/l10n/tb_fluent_migrations/completed/bug_1820700_select_thread.py create mode 100644 comm/python/l10n/tb_fluent_migrations/completed/bug_1823033_activity_indicator.py create mode 100644 comm/python/l10n/tb_fluent_migrations/completed/bug_1827261_add_enable_disable_compact_mode_options_to_folder_mode_context_menu.py create mode 100644 comm/python/l10n/tb_fluent_migrations/completed/bug_1827891_dnt_prefs_learn_more.py create mode 100644 comm/python/l10n/tb_fluent_migrations/completed/bug_1828340_aboutdialog_layout_fixes.py create mode 100644 comm/python/l10n/tb_fluent_migrations/completed/bug_1830004_folder_quota.py create mode 100644 comm/python/l10n/tb_fluent_migrations/completed/bug_1834662_cal_enable78.py create mode 100644 comm/python/l10n/tb_fluent_migrations/completed/bug_1834662_extensions_to_fluent.py create mode 100644 comm/python/l10n/tbxchannel/__init__.py create mode 100644 comm/python/l10n/tbxchannel/l10n_merge.py create mode 100644 comm/python/l10n/tbxchannel/quarantine_to_strings.py create mode 100644 comm/python/l10n/tbxchannel/tb_migration_test.py (limited to 'comm/python/l10n') diff --git a/comm/python/l10n/l10n_clone/l10n_clone.py b/comm/python/l10n/l10n_clone/l10n_clone.py new file mode 100644 index 0000000000..899ad4a212 --- /dev/null +++ b/comm/python/l10n/l10n_clone/l10n_clone.py @@ -0,0 +1,96 @@ +# 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/. +""" +Download and combine translations from l10n-central and comm-l10n for +use by mach build installers-$AB_CD and mach build langpack-$AB_CD. +""" + +import argparse +import json +import os +import sys +import tempfile +from pathlib import Path + +from mozpack.copier import FileCopier +from mozpack.files import FileFinder +from mozversioncontrol.repoupdate import update_mercurial_repo + +COMM_PATH = (Path(__file__).parent / "../../..").resolve() +GECKO_PATH = COMM_PATH.parent +COMM_PYTHON_L10N = os.path.join(COMM_PATH, "python/l10n") +sys.path.insert(1, COMM_PYTHON_L10N) + +from tbxchannel.l10n_merge import ( + COMM_L10N, + COMM_STRINGS_PATTERNS, + GECKO_STRINGS_PATTERNS, + L10N_CENTRAL, +) + +ALL_LOCALES = [l.rstrip() for l in (COMM_PATH / "mail/locales/all-locales").open().readlines()] + + +def tb_locale(locale): + if locale in ALL_LOCALES: + return locale + raise argparse.ArgumentTypeError("Locale {} invalid.".format(locale)) + + +def get_revision(project, locale): + json_file = { + "browser": GECKO_PATH / "browser/locales/l10n-changesets.json", + "mail": COMM_PATH / "mail/locales/l10n-changesets.json", + }.get(project) + if json_file is None: + raise Exception(f"Invalid project {project} for l10n-changesets.json!") + + with open(json_file) as fp: + changesets = json.load(fp) + + revision = changesets.get(locale, {}).get("revision") + if revision is None: + raise Exception(f"Locale {locale} not found in {project} l10n-changesets.json!") + + return revision + + +def get_strings_repos(locale, destination): + with tempfile.TemporaryDirectory() as tmproot: + central_url = "{}/{}".format(L10N_CENTRAL, locale) + l10n_central = Path(tmproot) / "l10n-central" + l10n_central.mkdir() + central_path = l10n_central / locale + central_revision = get_revision("browser", locale) + update_mercurial_repo("hg", central_url, central_path, revision=central_revision) + + comm_l10n = Path(tmproot) / "comm-l10n" + comm_revision = get_revision("mail", locale) + update_mercurial_repo("hg", COMM_L10N, comm_l10n, revision=comm_revision) + + file_copier = FileCopier() + + def add_to_registry(base_path, patterns): + finder = FileFinder(base_path) + for pattern in patterns: + for _filepath, _fileobj in finder.find(pattern.format(lang=locale)): + file_copier.add(_filepath, _fileobj) + + add_to_registry(l10n_central, GECKO_STRINGS_PATTERNS) + add_to_registry(comm_l10n, COMM_STRINGS_PATTERNS) + + file_copier.copy(str(destination)) + + +def main(): + parser = argparse.ArgumentParser(description="Download translated strings from comm-l10n") + parser.add_argument("locale", help="The locale to download", type=tb_locale) + parser.add_argument("dest_path", help="Path where locale will be downloaded to.", type=Path) + + args = parser.parse_args() + get_strings_repos(args.locale, args.dest_path) + + +if __name__ == "__main__": + main() diff --git a/comm/python/l10n/mach_commands.py b/comm/python/l10n/mach_commands.py new file mode 100644 index 0000000000..e4cfbfcf30 --- /dev/null +++ b/comm/python/l10n/mach_commands.py @@ -0,0 +1,264 @@ +# 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/. + +import argparse +import logging +import os.path +from pathlib import Path + +from mutlh.decorators import Command, CommandArgument + + +# https://stackoverflow.com/a/14117511 +def _positive_int(value): + value = int(value) + if value <= 0: + raise argparse.ArgumentTypeError(f"{value} must be a positive integer.") + return value + + +def _retry_run_process(command_context, *args, error_msg=None, **kwargs): + try: + return command_context.run_process(*args, **kwargs) + except Exception as exc: + raise Exception(error_msg or str(exc)) from exc + + +def _get_rev(command_context, strings_path): + result = [] + + def save_output(line): + result.append(line) + + status = _retry_run_process( + command_context, + [ + "hg", + "--cwd", + str(strings_path), + "log", + "-r", + ".", + "--template", + "{node}\n", + ], + line_handler=save_output, + ) + if status == 0: + return "\n".join(result) + raise Exception(f"Failed to get head revision: {status}") + + +@Command( + "tb-l10n-x-channel", + category="thunderbird", + description="Create cross-channel content for Thunderbird (comm-strings).", +) +@CommandArgument( + "--strings-path", + "-s", + metavar="en-US", + type=Path, + default=Path("en-US"), + help="Path to mercurial repository for comm-strings-quarantine", +) +@CommandArgument( + "--outgoing-path", + "-o", + type=Path, + help="create an outgoing() patch if there are changes", +) +@CommandArgument( + "--attempts", + type=_positive_int, + default=1, + help="Number of times to try (for automation)", +) +@CommandArgument( + "--ssh-secret", + action="store", + help="Taskcluster secret to use to push (for automation)", +) +@CommandArgument( + "actions", + choices=("prep", "create", "push", "clean"), + nargs="+", + # This help block will be poorly formatted until we fix bug 1714239 + help=""" + "prep": clone repos and pull heads. + "create": create the en-US strings commit an optionally create an + outgoing() patch. + "push": push the en-US strings to the quarantine repo. + "clean": clean up any sub-repos. + """, +) +def tb_cross_channel( + command_context, + strings_path, + outgoing_path, + actions, + attempts, + ssh_secret, + **kwargs, +): + """Run Thunderbird's l10n cross-channel content generation.""" + from tbxchannel import TB_XC_NOTIFICATION_TMPL, get_thunderbird_xc_config + from tbxchannel.l10n_merge import COMM_STRINGS_QUARANTINE + + from rocbuild.notify import email_notification + + kwargs.update( + { + "strings_path": strings_path, + "outgoing_path": outgoing_path, + "actions": actions, + "attempts": attempts, + "ssh_secret": ssh_secret, + "get_config": get_thunderbird_xc_config, + } + ) + command_context._mach_context.commands.dispatch( + "l10n-cross-channel", command_context._mach_context, **kwargs + ) + if os.path.exists(outgoing_path): + head_rev = _get_rev(command_context, strings_path) + rev_url = f"{COMM_STRINGS_QUARANTINE}/rev/{head_rev}" + + notification_body = TB_XC_NOTIFICATION_TMPL.format(rev_url=rev_url) + email_notification("X-channel comm-strings-quarantine updated", notification_body) + + +@Command( + "tb-add-missing-ftls", + category="thunderbird", + description="Add missing FTL files after l10n merge.", +) +@CommandArgument( + "--merge", + type=Path, + help="Merge path base", +) +@CommandArgument( + "locale", + type=str, + help="Locale code", +) +def tb_add_missing_ftls(command_context, merge, locale): + """ + Command to create empty FTL files for incomplete localizations to + avoid over-zealous en-US fallback as described in bug 1586984. This + mach command is based on the script used to update the l10n-central + repositories. It gets around the need to have write access to those + repositories in favor of creating the files during l10m-repackaging. + This code assumes that mach compare-locales --merge has already run. + """ + from missing_ftl import add_missing_ftls, get_lang_ftls, get_source_ftls + + print("Checking for missing .ftl files in locale {}".format(locale)) + comm_src_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), "../..")) + source_files = get_source_ftls(comm_src_dir) + + l10n_path = os.path.join(merge, locale) + locale_files = get_lang_ftls(l10n_path) + + add_missing_ftls(l10n_path, source_files, locale_files) + + +@Command( + "tb-fluent-migration-test", + category="thunderbird", + description="Test Fluent migration recipes.", +) +@CommandArgument("test_paths", nargs="*", metavar="N", help="Recipe paths to test.") +def run_migration_tests(command_context, test_paths=None, **kwargs): + if not test_paths: + test_paths = [] + command_context.activate_virtualenv() + + from tbxchannel.tb_migration_test import inspect_migration, prepare_object_dir, test_migration + + rv = 0 + with_context = [] + for to_test in test_paths: + try: + context = inspect_migration(to_test) + for issue in context["issues"]: + command_context.log( + logging.ERROR, + "tb-fluent-migration-test", + { + "error": issue["msg"], + "file": to_test, + }, + "ERROR in {file}: {error}", + ) + if context["issues"]: + continue + with_context.append( + { + "to_test": to_test, + "references": context["references"], + } + ) + except Exception as e: + command_context.log( + logging.ERROR, + "tb-fluent-migration-test", + {"error": str(e), "file": to_test}, + "ERROR in {file}: {error}", + ) + rv |= 1 + obj_dir = prepare_object_dir(command_context) + for context in with_context: + rv |= test_migration(command_context, obj_dir, **context) + return rv + + +from mutlh.decorators import Command, CommandArgument + + +@Command( + "tb-l10n-quarantine-to-strings", + category="thunderbird", + description="Publish quarantines strings to comm-l10n.", +) +@CommandArgument( + "--quarantine-path", + "-q", + type=Path, + help="Path to comm-strings-quarantine repo", +) +@CommandArgument( + "--comm-l10n-path", + "-l", + type=Path, + help="Path to comm-l10n repo", +) +@CommandArgument( + "actions", + choices=("clean", "prep", "migrate", "push"), + nargs="+", + # This help block will be poorly formatted until we fix bug 1714239 + help=""" + "clean": remove existing clones of quarantine and comm-l10n repos + "prep": clone a new repository or update an existing one to latest rev + "migrate": update comm-l10n en_US from quarantine + "push": push comm-l10n + """, +) +def quarantine_to_strings( + command_context, + quarantine_path, + comm_l10n_path, + actions, + **kwargs, +): + """Publish strings in Thunderbird's comm-l10n cross-channel repository from + comm-strings-quarantine.""" + from tbxchannel.quarantine_to_strings import publish_strings + + command_context._set_log_level(True) + command_context.activate_virtualenv() + command_context.log_manager.enable_unstructured() + publish_strings(command_context, quarantine_path, comm_l10n_path, actions, **kwargs) diff --git a/comm/python/l10n/missing_ftl/__init__.py b/comm/python/l10n/missing_ftl/__init__.py new file mode 100644 index 0000000000..1e90db6d5b --- /dev/null +++ b/comm/python/l10n/missing_ftl/__init__.py @@ -0,0 +1,59 @@ +# 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/. + +import os + + +def walk_path(folder_path, prefix): + file_list = [] + for root, dirs, files in os.walk(folder_path, followlinks=True): + for file_name in files: + if os.path.splitext(file_name)[1] == ".ftl": + file_name = os.path.relpath(os.path.join(root, file_name), folder_path) + file_name = os.path.join(prefix, file_name) + file_list.append(file_name) + file_list.sort() + + return file_list + + +def get_source_ftls(comm_src_dir): + """Find ftl files in en-US mail and calendar.""" + file_list = [] + for d in ["mail", "calendar"]: + folder_path = os.path.join(comm_src_dir, d, "locales/en-US") + file_list += walk_path(folder_path, d) + return file_list + + +def get_lang_ftls(l10n_path): + """Find ftl files in the merge directory.""" + file_list = [] + for d in ["mail", "calendar"]: + folder_path = os.path.join(l10n_path, d) + file_list += walk_path(folder_path, d) + return file_list + + +def add_missing_ftls(l10n_path, source_files, locale_files): + """ + For any ftl files that are in source_files but missing in locale_files, + create a placeholder file. + """ + for file_name in source_files: + if file_name not in locale_files: + full_file_name = os.path.join(l10n_path, file_name) + file_path = os.path.dirname(full_file_name) + if not os.path.isdir(file_path): + # Create missing folder + print("Creating missing folder: {}".format(os.path.relpath(file_path, l10n_path))) + os.makedirs(file_path) + + print("Adding missing file: {}".format(file_name)) + with open(full_file_name, "w") as f: + f.write( + "# This Source Code Form is subject to the terms of the Mozilla Public\n" + "# License, v. 2.0. If a copy of the MPL was not distributed with this\n" + "# file, You can obtain one at http://mozilla.org/MPL/2.0/.\n" + ) diff --git a/comm/python/l10n/tb_fluent_migrations/__init__.py b/comm/python/l10n/tb_fluent_migrations/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/comm/python/l10n/tb_fluent_migrations/bug_1827199_multi_message_view.py b/comm/python/l10n/tb_fluent_migrations/bug_1827199_multi_message_view.py new file mode 100644 index 0000000000..47cc910b67 --- /dev/null +++ b/comm/python/l10n/tb_fluent_migrations/bug_1827199_multi_message_view.py @@ -0,0 +1,33 @@ +# Any copyright is dedicated to the Public Domain. +# http://creativecommons.org/publicdomain/zero/1.0/ + +from fluent.migratetb import COPY_PATTERN +from fluent.migratetb.helpers import transforms_from + + +def migrate(ctx): + """Bug 1827199 - Message summary preview header buttons are not keyboard accessible""" + + target = reference = "mail/locales/en-US/messenger/multimessageview.ftl" + ctx.add_transforms( + target, + reference, + transforms_from( + """ +multi-message-window-title = + .title = {{COPY_PATTERN(from_path, "window.title")}} + +selected-messages-label = + .label = {{COPY_PATTERN(from_path, "selectedmessages.label")}} + +multi-message-archive-button = + .label = {{COPY_PATTERN(from_path, "archiveButton.label")}} + .tooltiptext = {{COPY_PATTERN(from_path, "archiveButton.label")}} + +multi-message-delete-button = + .label = {{COPY_PATTERN(from_path, "deleteButton.label")}} + .tooltiptext = {{COPY_PATTERN(from_path, "deleteButton.label")}} + """, + from_path="mail/locales/en-US/chrome/messenger/multimessageview.dtd", + ), + ) diff --git a/comm/python/l10n/tb_fluent_migrations/bug_1831422_backupKeyPassword.py b/comm/python/l10n/tb_fluent_migrations/bug_1831422_backupKeyPassword.py new file mode 100644 index 0000000000..1c86a338a4 --- /dev/null +++ b/comm/python/l10n/tb_fluent_migrations/bug_1831422_backupKeyPassword.py @@ -0,0 +1,25 @@ +# Any copyright is dedicated to the Public Domain. +# http://creativecommons.org/publicdomain/zero/1.0/ + +from fluent.migratetb import COPY_PATTERN +from fluent.migratetb.helpers import transforms_from + + +def migrate(ctx): + """Bug 1831422 - migrations in OpenPGP key backup dialog""" + + target = reference = "mail/messenger/openpgp/backupKeyPassword.ftl" + ctx.add_transforms( + target, + reference, + transforms_from( + """ +set-password-window-title = {{COPY_PATTERN(from_path, "set-password-window.title")}} + +set-password-backup-pw-label = {{COPY_PATTERN(from_path, "set-password-backup-pw.value")}} + +set-password-backup-pw2-label = {{COPY_PATTERN(from_path, "set-password-repeat-backup-pw.value")}} + """, + from_path="mail/messenger/openpgp/backupKeyPassword.ftl", + ), + ) diff --git a/comm/python/l10n/tb_fluent_migrations/bug_1833042_unfied_toolbar_button_style.py b/comm/python/l10n/tb_fluent_migrations/bug_1833042_unfied_toolbar_button_style.py new file mode 100644 index 0000000000..108f48474e --- /dev/null +++ b/comm/python/l10n/tb_fluent_migrations/bug_1833042_unfied_toolbar_button_style.py @@ -0,0 +1,25 @@ +# Any copyright is dedicated to the Public Domain. +# http://creativecommons.org/publicdomain/zero/1.0/ + +from fluent.migrate.helpers import transforms_from +from fluent.migrate import COPY_PATTERN + + +def migrate(ctx): + """Bug 1833042 - Don't automatically update the button style preference when changed in the unified toolbar customization panel, part {index}.""" + ctx.add_transforms( + "mail/messenger/unifiedToolbar.ftl", + "mail/messenger/unifiedToolbar.ftl", + transforms_from( + """ +customize-button-style-icons-beside-text-option = {COPY_PATTERN(from_path, "customize-button-style-icons-beside-text.label")} + +customize-button-style-icons-above-text-option = {COPY_PATTERN(from_path, "customize-button-style-icons-above-text.label")} + +customize-button-style-icons-only-option = {COPY_PATTERN(from_path, "customize-button-style-icons-only.label")} + +customize-button-style-text-only-option = {COPY_PATTERN(from_path, "customize-button-style-text-only.label")} + """, + from_path="mail/messenger/unifiedToolbar.ftl", + ), + ) diff --git a/comm/python/l10n/tb_fluent_migrations/bug_1838109_changeExpiryDlg.py b/comm/python/l10n/tb_fluent_migrations/bug_1838109_changeExpiryDlg.py new file mode 100644 index 0000000000..68566c4131 --- /dev/null +++ b/comm/python/l10n/tb_fluent_migrations/bug_1838109_changeExpiryDlg.py @@ -0,0 +1,27 @@ +# Any copyright is dedicated to the Public Domain. +# http://creativecommons.org/publicdomain/zero/1.0/ + +from fluent.migratetb import COPY_PATTERN +from fluent.migratetb.helpers import transforms_from + + +def migrate(ctx): + """Bug 1838109 - migrate some strings in changeExpiryDlg.xhtml""" + + target = reference = "mail/messenger/openpgp/changeExpiryDlg.ftl" + ctx.add_transforms( + target, + reference, + transforms_from( + """ +openpgp-change-expiry-title = {{COPY_PATTERN(from_path, "openpgp-change-key-expiry-title.title")}} + +expire-no-change-label = {{COPY_PATTERN(from_path, "expire-dont-change.label")}} + +expire-in-time-label = {{COPY_PATTERN(from_path, "expire-in-label.label")}} + +expire-never-expire-label = {{COPY_PATTERN(from_path, "expire-never-label.label")}} + """, + from_path="mail/messenger/openpgp/changeExpiryDlg.ftl", + ), + ) diff --git a/comm/python/l10n/tb_fluent_migrations/bug_1838770_properties_menu_item.py b/comm/python/l10n/tb_fluent_migrations/bug_1838770_properties_menu_item.py new file mode 100644 index 0000000000..04e15628b8 --- /dev/null +++ b/comm/python/l10n/tb_fluent_migrations/bug_1838770_properties_menu_item.py @@ -0,0 +1,56 @@ +# Any copyright is dedicated to the Public Domain. +# http://creativecommons.org/publicdomain/zero/1.0/ + +from fluent.migratetb import COPY + +import fluent.syntax.ast as FTL + + +def migrate(ctx): + """Bug 1838770 - Edit > Folder Properties doesn't work, part {index}.""" + source = "mail/chrome/messenger/messenger.dtd" + dest = "mail/messenger/messenger.ftl" + ctx.add_transforms( + dest, + dest, + [ + FTL.Message( + id=FTL.Identifier("menu-edit-properties"), + attributes=[ + FTL.Attribute( + id=FTL.Identifier("label"), value=COPY(source, "folderPropsCmd2.label") + ), + FTL.Attribute( + id=FTL.Identifier("accesskey"), + value=COPY(source, "folderPropsCmd.accesskey"), + ), + ], + ), + FTL.Message( + id=FTL.Identifier("menu-edit-folder-properties"), + attributes=[ + FTL.Attribute( + id=FTL.Identifier("label"), + value=COPY(source, "folderPropsFolderCmd2.label"), + ), + FTL.Attribute( + id=FTL.Identifier("accesskey"), + value=COPY(source, "folderPropsCmd.accesskey"), + ), + ], + ), + FTL.Message( + id=FTL.Identifier("menu-edit-newsgroup-properties"), + attributes=[ + FTL.Attribute( + id=FTL.Identifier("label"), + value=COPY(source, "folderPropsNewsgroupCmd2.label"), + ), + FTL.Attribute( + id=FTL.Identifier("accesskey"), + value=COPY(source, "folderPropsCmd.accesskey"), + ), + ], + ), + ], + ) diff --git a/comm/python/l10n/tb_fluent_migrations/completed/bug_1703164_calendar_ics_file_dialog.py b/comm/python/l10n/tb_fluent_migrations/completed/bug_1703164_calendar_ics_file_dialog.py new file mode 100644 index 0000000000..4e7df08f73 --- /dev/null +++ b/comm/python/l10n/tb_fluent_migrations/completed/bug_1703164_calendar_ics_file_dialog.py @@ -0,0 +1,20 @@ +# Any copyright is dedicated to the Public Domain. +# http://creativecommons.org/publicdomain/zero/1.0/ + +from fluent.migrate import COPY_PATTERN +from fluent.migrate.helpers import transforms_from + + +def migrate(ctx): + """Bug 1703164 - convert calendar/base/content/dialogs/calendar-ics-file-dialog.xhtml to html""" + + ctx.add_transforms( + "calendar/calendar/calendar-ics-file-dialog.ftl", + "calendar/calendar/calendar-ics-file-dialog.ftl", + transforms_from( + """ +calendar-ics-file-window-title = {{COPY_PATTERN(from_path, "calendar-ics-file-window-2.title")}} + """, + from_path="calendar/calendar/calendar-ics-file-dialog.ftl", + ), + ) diff --git a/comm/python/l10n/tb_fluent_migrations/completed/bug_1703164_calendar_uri_redirect_dialog.py b/comm/python/l10n/tb_fluent_migrations/completed/bug_1703164_calendar_uri_redirect_dialog.py new file mode 100644 index 0000000000..cd4e681da0 --- /dev/null +++ b/comm/python/l10n/tb_fluent_migrations/completed/bug_1703164_calendar_uri_redirect_dialog.py @@ -0,0 +1,20 @@ +# Any copyright is dedicated to the Public Domain. +# http://creativecommons.org/publicdomain/zero/1.0/ + +from fluent.migrate import COPY_PATTERN +from fluent.migrate.helpers import transforms_from + + +def migrate(ctx): + """Bug 1703164 - convert calendar/base/content/dialogs/calendar-uri-redirect-dialog.xhtml to top level html""" + + ctx.add_transforms( + "calendar/calendar/calendar-uri-redirect-dialog.ftl", + "calendar/calendar/calendar-uri-redirect-dialog.ftl", + transforms_from( + """ +calendar-uri-redirect-window-title = {{COPY_PATTERN(from_path, "calendar-uri-redirect-window.title")}} + """, + from_path="calendar/calendar/calendar-uri-redirect-dialog.ftl", + ), + ) diff --git a/comm/python/l10n/tb_fluent_migrations/completed/bug_1731837_delete_commands.py b/comm/python/l10n/tb_fluent_migrations/completed/bug_1731837_delete_commands.py new file mode 100644 index 0000000000..fc045d1ed6 --- /dev/null +++ b/comm/python/l10n/tb_fluent_migrations/completed/bug_1731837_delete_commands.py @@ -0,0 +1,114 @@ +# Any copyright is dedicated to the Public Domain. +# http://creativecommons.org/publicdomain/zero/1.0/ + +import re + +from fluent.migratetb import COPY, COPY_PATTERN +from fluent.migratetb.helpers import VARIABLE_REFERENCE +from fluent.migratetb.transforms import Transform, TransformPattern + +import fluent.syntax.ast as FTL + + +def migrate(ctx): + """Bug 1731837 - Fix multiple problems with the labelling of Delete commands, part {index}.""" + source = "mail/chrome/messenger/messenger.dtd" + dest = "mail/messenger/messenger.ftl" + ctx.add_transforms( + dest, + dest, + [ + FTL.Message( + id=FTL.Identifier("menu-edit-delete-folder"), + attributes=[ + FTL.Attribute( + id=FTL.Identifier("label"), value=COPY(source, "deleteFolderCmd.label") + ), + FTL.Attribute( + id=FTL.Identifier("accesskey"), + value=COPY(source, "deleteFolderCmd.accesskey"), + ), + ], + ), + FTL.Message( + id=FTL.Identifier("menu-edit-delete-messages"), + attributes=[ + FTL.Attribute( + id=FTL.Identifier("label"), + value=Transform.pattern_of( + FTL.SelectExpression( + selector=VARIABLE_REFERENCE("count"), + variants=[ + FTL.Variant( + key=FTL.Identifier("one"), + value=COPY(source, "deleteMsgCmd.label"), + ), + FTL.Variant( + key=FTL.Identifier("other"), + default=True, + value=COPY(source, "deleteMsgsCmd.label"), + ), + ], + ) + ), + ), + FTL.Attribute( + id=FTL.Identifier("accesskey"), + value=COPY(source, "deleteMsgCmd.accesskey"), + ), + ], + ), + FTL.Message( + id=FTL.Identifier("menu-edit-undelete-messages"), + attributes=[ + FTL.Attribute( + id=FTL.Identifier("label"), + value=Transform.pattern_of( + FTL.SelectExpression( + selector=VARIABLE_REFERENCE("count"), + variants=[ + FTL.Variant( + key=FTL.Identifier("one"), + value=COPY(source, "undeleteMsgCmd.label"), + ), + FTL.Variant( + key=FTL.Identifier("other"), + default=True, + value=COPY(source, "undeleteMsgsCmd.label"), + ), + ], + ) + ), + ), + FTL.Attribute( + id=FTL.Identifier("accesskey"), + value=COPY(source, "undeleteMsgCmd.accesskey"), + ), + ], + ), + FTL.Message( + id=FTL.Identifier("mail-context-undelete-messages"), + attributes=[ + FTL.Attribute( + id=FTL.Identifier("label"), + value=Transform.pattern_of( + FTL.SelectExpression( + selector=VARIABLE_REFERENCE("count"), + variants=[ + FTL.Variant( + key=FTL.Identifier("one"), + value=COPY(source, "undeleteMsgCmd.label"), + ), + FTL.Variant( + key=FTL.Identifier("other"), + default=True, + value=COPY(source, "undeleteMsgsCmd.label"), + ), + ], + ) + ), + ) + ], + ), + ], + ) diff --git a/comm/python/l10n/tb_fluent_migrations/completed/bug_1798509_unified_toolbar_customization.py b/comm/python/l10n/tb_fluent_migrations/completed/bug_1798509_unified_toolbar_customization.py new file mode 100644 index 0000000000..7ac296ec35 --- /dev/null +++ b/comm/python/l10n/tb_fluent_migrations/completed/bug_1798509_unified_toolbar_customization.py @@ -0,0 +1,52 @@ +# Any copyright is dedicated to the Public Domain. +# http://creativecommons.org/publicdomain/zero/1.0/ + +from fluent.migrate import COPY_PATTERN +from fluent.migrate.helpers import transforms_from + + +def migrate(ctx): + """Bug 1798509 - Unified toolbar customization fluent migration part {index}.""" + + ctx.add_transforms( + "mail/messenger/unifiedToolbar.ftl", + "mail/messenger/unifiedToolbar.ftl", + transforms_from( + """ +customize-menu-customize = + .label = { COPY(from_path, "customizeToolbar.label") } + """, + from_path="mail/chrome/messenger/messenger.dtd", + ), + ) + ctx.add_transforms( + "mail/messenger/unifiedToolbar.ftl", + "mail/messenger/unifiedToolbar.ftl", + transforms_from( + """ +customize-space-mail = { COPY_PATTERN(from_path, "spaces-toolbar-button-mail2.title") } + +customize-space-addressbook = { COPY_PATTERN(from_path, "spaces-toolbar-button-address-book2.title") } + +customize-space-calendar = { COPY_PATTERN(from_path, "spaces-toolbar-button-calendar2.title") } + +customize-space-tasks = { COPY_PATTERN(from_path, "spaces-toolbar-button-tasks2.title") } + +customize-space-chat = { COPY_PATTERN(from_path, "spaces-toolbar-button-chat2.title") } + +customize-space-settings = { COPY_PATTERN(from_path, "spaces-toolbar-button-settings2.title") } + """, + from_path="mail/messenger/messenger.ftl", + ), + ) + ctx.add_transforms( + "mail/messenger/unifiedToolbar.ftl", + "mail/messenger/unifiedToolbar.ftl", + transforms_from( + """ +customize-button-style-icons-beside-text = + .label = { COPY(from_path, "iconsBesideText.label") } + """, + from_path="mail/chrome/messenger/customizeToolbar.dtd", + ), + ) diff --git a/comm/python/l10n/tb_fluent_migrations/completed/bug_1803705_thread_pane.py b/comm/python/l10n/tb_fluent_migrations/completed/bug_1803705_thread_pane.py new file mode 100644 index 0000000000..b3f41b1c5a --- /dev/null +++ b/comm/python/l10n/tb_fluent_migrations/completed/bug_1803705_thread_pane.py @@ -0,0 +1,111 @@ +# coding=utf8 + +# Any copyright is dedicated to the Public Domain. +# http://creativecommons.org/publicdomain/zero/1.0/ + +from fluent.migrate.helpers import transforms_from +from fluent.migrate import COPY + + +def migrate(ctx): + """Bug 1803705 - Migrate thread tree strings to fluent, part {index}.""" + + ctx.add_transforms( + "mail/messenger/treeView.ftl", + "mail/messenger/treeView.ftl", + transforms_from( + """ +tree-list-view-column-picker = + .title = { COPY(from_path, "columnChooser2.tooltip") } +""", + from_path="mail/chrome/messenger/messenger.dtd", + ), + ) + + ctx.add_transforms( + "mail/messenger/about3Pane.ftl", + "mail/messenger/about3Pane.ftl", + transforms_from( + """ +threadpane-column-header-select = + .title = { COPY(from_path, "selectColumn.tooltip") } +threadpane-column-label-select = + .label = { COPY(from_path, "selectColumn.label") } +threadpane-column-label-thread = + .label = { COPY(from_path, "threadColumn.label") } +threadpane-column-header-flagged = + .title = { COPY(from_path, "starredColumn2.tooltip") } +threadpane-column-label-flagged = + .label = { COPY(from_path, "starredColumn.label") } +threadpane-column-header-attachments = + .title = { COPY(from_path, "attachmentColumn2.tooltip") } +threadpane-column-label-attachments = + .label = { COPY(from_path, "attachmentColumn.label") } +threadpane-column-header-sender = { COPY(from_path, "fromColumn.label") } + .title = { COPY(from_path, "fromColumn2.tooltip") } +threadpane-column-label-sender = + .label = { COPY(from_path, "fromColumn.label") } +threadpane-column-header-recipient = { COPY(from_path, "recipientColumn.label") } + .title = { COPY(from_path, "recipientColumn2.tooltip") } +threadpane-column-label-recipient = + .label = { COPY(from_path, "recipientColumn.label") } +threadpane-column-header-correspondents = { COPY(from_path, "correspondentColumn.label") } + .title = { COPY(from_path, "correspondentColumn2.tooltip") } +threadpane-column-label-correspondents = + .label = { COPY(from_path, "correspondentColumn.label") } +threadpane-column-header-subject = { COPY(from_path, "subjectColumn.label") } + .title = { COPY(from_path, "subjectColumn2.tooltip") } +threadpane-column-label-subject = + .label = { COPY(from_path, "subjectColumn.label") } +threadpane-column-header-date = { COPY(from_path, "dateColumn.label") } + .title = { COPY(from_path, "dateColumn2.tooltip") } +threadpane-column-label-date = + .label = { COPY(from_path, "dateColumn.label") } +threadpane-column-header-received = { COPY(from_path, "receivedColumn.label") } + .title = { COPY(from_path, "receivedColumn2.tooltip") } +threadpane-column-label-received = + .label = { COPY(from_path, "receivedColumn.label") } +threadpane-column-header-status = { COPY(from_path, "statusColumn.label") } + .title = { COPY(from_path, "statusColumn2.tooltip") } +threadpane-column-label-status = + .label = { COPY(from_path, "statusColumn.label") } +threadpane-column-header-size = { COPY(from_path, "sizeColumn.label") } + .title = { COPY(from_path, "sizeColumn2.tooltip") } +threadpane-column-label-size = + .label = { COPY(from_path, "sizeColumn.label") } +threadpane-column-header-tags = { COPY(from_path, "tagsColumn.label") } + .title = { COPY(from_path, "tagsColumn2.tooltip") } +threadpane-column-label-tags = + .label = { COPY(from_path, "tagsColumn.label") } +threadpane-column-header-account = { COPY(from_path, "accountColumn.label") } + .title = { COPY(from_path, "accountColumn2.tooltip") } +threadpane-column-label-account = + .label = { COPY(from_path, "accountColumn.label") } +threadpane-column-header-priority = { COPY(from_path, "priorityColumn.label") } + .title = { COPY(from_path, "priorityColumn2.tooltip") } +threadpane-column-label-priority = + .label = { COPY(from_path, "priorityColumn.label") } +threadpane-column-header-unread = { COPY(from_path, "unreadColumn.label") } + .title = { COPY(from_path, "unreadColumn2.tooltip") } +threadpane-column-label-unread = + .label = { COPY(from_path, "unreadColumn.label") } +threadpane-column-header-total = { COPY(from_path, "totalColumn.label") } + .title = { COPY(from_path, "totalColumn2.tooltip") } +threadpane-column-label-total = + .label = { COPY(from_path, "totalColumn.label") } +threadpane-column-header-location = { COPY(from_path, "locationColumn.label") } + .title = { COPY(from_path, "locationColumn2.tooltip") } +threadpane-column-label-location = + .label = { COPY(from_path, "locationColumn.label") } +threadpane-column-header-id = { COPY(from_path, "idColumn.label") } + .title = { COPY(from_path, "idColumn2.tooltip") } +threadpane-column-label-id = + .label = { COPY(from_path, "idColumn.label") } +threadpane-column-header-delete = + .title = { COPY(from_path, "deleteColumn.tooltip") } +threadpane-column-label-delete = + .label = { COPY(from_path, "deleteColumn.label") } +""", + from_path="mail/chrome/messenger/messenger.dtd", + ), + ) diff --git a/comm/python/l10n/tb_fluent_migrations/completed/bug_1805746_calendar_view.py b/comm/python/l10n/tb_fluent_migrations/completed/bug_1805746_calendar_view.py new file mode 100644 index 0000000000..eec0fbe44e --- /dev/null +++ b/comm/python/l10n/tb_fluent_migrations/completed/bug_1805746_calendar_view.py @@ -0,0 +1,29 @@ +# coding=utf8 + +# Any copyright is dedicated to the Public Domain. +# http://creativecommons.org/publicdomain/zero/1.0/ + +from fluent.migrate.helpers import transforms_from +from fluent.migrate import COPY + + +def migrate(ctx): + """Bug 1805746 - Update Calendar View selection part {index}.""" + + ctx.add_transforms( + "calendar/calendar/calendar-widgets.ftl", + "calendar/calendar/calendar-widgets.ftl", + transforms_from( + """ +calendar-view-toggle-day = { COPY(from_path, "calendar.day.button.label") } + .title = { COPY(from_path, "calendar.day.button.tooltip") } +calendar-view-toggle-week = { COPY(from_path, "calendar.week.button.label") } + .title = { COPY(from_path, "calendar.week.button.tooltip") } +calendar-view-toggle-multiweek = { COPY(from_path, "calendar.multiweek.button.label") } + .title = { COPY(from_path, "calendar.multiweek.button.tooltip") } +calendar-view-toggle-month = { COPY(from_path, "calendar.month.button.label") } + .title = { COPY(from_path, "calendar.month.button.tooltip") } +""", + from_path="calendar/chrome/calendar/calendar.dtd", + ), + ) diff --git a/comm/python/l10n/tb_fluent_migrations/completed/bug_1805938_calendar_recurrence_ux.py b/comm/python/l10n/tb_fluent_migrations/completed/bug_1805938_calendar_recurrence_ux.py new file mode 100644 index 0000000000..715b475015 --- /dev/null +++ b/comm/python/l10n/tb_fluent_migrations/completed/bug_1805938_calendar_recurrence_ux.py @@ -0,0 +1,25 @@ +# coding=utf8 + +# Any copyright is dedicated to the Public Domain. +# http://creativecommons.org/publicdomain/zero/1.0/ + +from fluent.migrate.helpers import transforms_from +from fluent.migrate import COPY + + +def migrate(ctx): + """Bug 1805938 - Refactor recurrence calendar UX part {index}.""" + + source = "calendar/chrome/calendar/calendar-event-dialog.dtd" + reference = target = "calendar/calendar/calendar-recurrence-dialog.ftl" + + ctx.add_transforms( + target, + reference, + transforms_from( + """ +calendar-recurrence-preview-label = { COPY(from_path, "event.recurrence.preview.label") } +""", + from_path=source, + ), + ) diff --git a/comm/python/l10n/tb_fluent_migrations/completed/bug_1806567_quick_filter_bar_migration.py b/comm/python/l10n/tb_fluent_migrations/completed/bug_1806567_quick_filter_bar_migration.py new file mode 100644 index 0000000000..72967ef4d8 --- /dev/null +++ b/comm/python/l10n/tb_fluent_migrations/completed/bug_1806567_quick_filter_bar_migration.py @@ -0,0 +1,182 @@ +# coding=utf8 + +# Any copyright is dedicated to the Public Domain. +# http://creativecommons.org/publicdomain/zero/1.0/ + +import fluent.syntax.ast as FTL +from fluent.migrate.helpers import ( + MESSAGE_REFERENCE, + VARIABLE_REFERENCE, + transforms_from, +) +from fluent.migrate.transforms import ( + CONCAT, + PLURALS, + REPLACE, + REPLACE_IN_TEXT, + Transform, +) + + +def migrate(ctx): + """Bug 1806567 - Migrate Quick Filter Bar strings from DTD to FTL, part {index}""" + + source = "mail/chrome/messenger/quickFilterBar.dtd" + target1 = reference1 = "mail/messenger/about3Pane.ftl" + ctx.add_transforms( + target1, + reference1, + transforms_from( + """ + +quick-filter-bar-sticky = + .title = { COPY(from_path, "quickFilterBar.sticky.tooltip") } +quick-filter-bar-unread = + .title = { COPY(from_path, "quickFilterBar.unread.tooltip") } +quick-filter-bar-unread-label = { COPY(from_path, "quickFilterBar.unread.label") } +quick-filter-bar-starred = + .title = { COPY(from_path, "quickFilterBar.starred.tooltip") } +quick-filter-bar-starred-label = { COPY(from_path, "quickFilterBar.starred.label") } +quick-filter-bar-inaddrbook = + .title = { COPY(from_path, "quickFilterBar.inaddrbook.tooltip") } +quick-filter-bar-inaddrbook-label = { COPY(from_path, "quickFilterBar.inaddrbook.label") } +quick-filter-bar-tags = + .title = { COPY(from_path, "quickFilterBar.tags.tooltip") } +quick-filter-bar-tags-label = { COPY(from_path, "quickFilterBar.tags.label") } +quick-filter-bar-attachment = + .title = { COPY(from_path, "quickFilterBar.attachment.tooltip") } +quick-filter-bar-attachment-label = { COPY(from_path, "quickFilterBar.attachment.label") } +quick-filter-bar-no-results = { COPY(from_path, "quickFilterBar.resultsLabel.none") } +""", + from_path=source, + ), + ) + ctx.add_transforms( + target1, + reference1, + [ + FTL.Message( + id=FTL.Identifier("quick-filter-bar-results"), + value=PLURALS( + source, + "quickFilterBar.resultsLabel.some.formatString", + VARIABLE_REFERENCE("count"), + lambda text: REPLACE_IN_TEXT(text, {"#1": VARIABLE_REFERENCE("count")}), + ), + ), + FTL.Message( + id=FTL.Identifier("quick-filter-bar-textbox-shortcut"), + value=Transform.pattern_of( + FTL.SelectExpression( + selector=FTL.FunctionReference( + id=FTL.Identifier("PLATFORM"), + arguments=FTL.CallArguments(), + ), + variants=[ + FTL.Variant( + key=FTL.Identifier("macos"), + default=False, + value=REPLACE( + source, + "quickFilterBar.textbox.emptyText.keyLabel2.mac", + { + "<": FTL.TextElement(""), + "⇧⌘": FTL.TextElement("⇧ ⌘ "), + ">": FTL.TextElement(""), + }, + ), + ), + FTL.Variant( + key=FTL.Identifier("other"), + default=True, + value=REPLACE( + source, + "quickFilterBar.textbox.emptyText.keyLabel2.nonmac", + { + "<": FTL.TextElement(""), + ">": FTL.TextElement(""), + }, + ), + ), + ], + ) + ), + ), + FTL.Message( + id=FTL.Identifier("quick-filter-bar-textbox"), + attributes=[ + FTL.Attribute( + id=FTL.Identifier("placeholder"), + value=REPLACE( + source, + "quickFilterBar.textbox.emptyText.base1", + { + "#1": CONCAT( + FTL.TextElement("<"), + MESSAGE_REFERENCE("quick-filter-bar-textbox-shortcut"), + FTL.TextElement(">"), + ) + }, + ), + ), + ], + ), + ], + ) + ctx.add_transforms( + target1, + reference1, + transforms_from( + """ +quick-filter-bar-boolean-mode = + .title = { COPY(from_path, "quickFilterBar.booleanMode.tooltip") } +quick-filter-bar-boolean-mode-any = + .label = { COPY(from_path, "quickFilterBar.booleanModeAny.label") } + .title = { COPY(from_path, "quickFilterBar.booleanModeAny.tooltip") } +quick-filter-bar-boolean-mode-all = + .label = { COPY(from_path, "quickFilterBar.booleanModeAll.label") } + .title = { COPY(from_path, "quickFilterBar.booleanModeAll.tooltip") } +quick-filter-bar-text-filter-explanation = { COPY(from_path, "quickFilterBar.textFilter.explanation.label") } +quick-filter-bar-text-filter-sender = { COPY(from_path, "quickFilterBar.textFilter.sender.label") } +quick-filter-bar-text-filter-recipients = { COPY(from_path, "quickFilterBar.textFilter.recipients.label") } +quick-filter-bar-text-filter-subject = { COPY(from_path, "quickFilterBar.textFilter.subject.label") } +quick-filter-bar-text-filter-body = { COPY(from_path, "quickFilterBar.textFilter.body.label") } +quick-filter-bar-gloda-upsell-line1 = { COPY(from_path, "quickFilterBar.glodaUpsell.continueSearch") } +""", + from_path=source, + ), + ) + ctx.add_transforms( + target1, + reference1, + [ + FTL.Message( + id=FTL.Identifier("quick-filter-bar-gloda-upsell-line2"), + value=REPLACE( + source, + "quickFilterBar.glodaUpsell.pressEnterAndCurrent", + { + "#1": VARIABLE_REFERENCE("text"), + " '": FTL.TextElement(" ‘"), + "' ": FTL.TextElement("’ "), + }, + ), + ), + ], + ) + + target2 = reference2 = "mail/messenger/messenger.ftl" + ctx.add_transforms( + target2, + reference2, + transforms_from( + """ +quick-filter-bar-toggle = + .label = { COPY(from_path, "quickFilterBar.toggleBarVisibility.menu.label") } + .accesskey = { COPY(from_path, "quickFilterBar.toggleBarVisibility.menu.accesskey") } +quick-filter-bar-show = + .key = { COPY(from_path, "quickFilterBar.show.key2") } +""", + from_path=source, + ), + ) diff --git a/comm/python/l10n/tb_fluent_migrations/completed/bug_1809312_unified_toolbar_buttons.py b/comm/python/l10n/tb_fluent_migrations/completed/bug_1809312_unified_toolbar_buttons.py new file mode 100644 index 0000000000..6558f5d6a7 --- /dev/null +++ b/comm/python/l10n/tb_fluent_migrations/completed/bug_1809312_unified_toolbar_buttons.py @@ -0,0 +1,218 @@ +# Any copyright is dedicated to the Public Domain. +# http://creativecommons.org/publicdomain/zero/1.0/ + +from fluent.migrate import COPY_PATTERN +from fluent.migrate.helpers import transforms_from + + +def migrate(ctx): + """Bug 1809312 - Implement mail space actions for unified toolbar fluent migration part {index}.""" + + ctx.add_transforms( + "mail/messenger/unifiedToolbarItems.ftl", + "mail/messenger/unifiedToolbarItems.ftl", + transforms_from( + """ +spacer-label = { COPY(from_path, "springTitle") } + """, + from_path="mail/chrome/messenger/customizeToolbar.properties", + ), + ) + ctx.add_transforms( + "mail/messenger/unifiedToolbarItems.ftl", + "mail/messenger/unifiedToolbarItems.ftl", + transforms_from( + """ +toolbar-write-message-label = { COPY(from_path, "newMsgButton.label") } + +toolbar-write-message = + .title = { COPY(from_path, "newMsgButton.tooltip") } + +toolbar-folder-location-label = { COPY(from_path, "folderLocationToolbarItem.title") } + +toolbar-get-messages-label = { COPY(from_path, "getMsgButton1.label") } + +toolbar-reply-label = { COPY(from_path, "replyButton.label") } + +toolbar-reply = + .title = { COPY(from_path, "replyButton.tooltip") } + +toolbar-reply-all-label = { COPY(from_path, "replyAllButton.label") } + +toolbar-reply-all = + .title = { COPY(from_path, "replyAllButton.tooltip") } + +toolbar-reply-to-list-label = { COPY(from_path, "replyListButton.label") } + +toolbar-reply-to-list = + .title = { COPY(from_path, "replyListButton.tooltip") } + +toolbar-archive-label = { COPY(from_path, "archiveButton.label") } + +toolbar-archive = + .title = { COPY(from_path, "archiveButton.tooltip") } + +toolbar-conversation-label = { COPY(from_path, "openConversationButton.label") } + +toolbar-conversation = + .title = { COPY(from_path, "openMsgConversationButton.tooltip") } + +toolbar-previous-unread-label = { COPY(from_path, "previousButtonToolbarItem.label") } + +toolbar-previous-unread = + .title = { COPY(from_path, "previousButton.tooltip") } + +toolbar-previous-label = { COPY(from_path, "previousButton.label") } + +toolbar-previous = + .title = { COPY(from_path, "previousMsgButton.tooltip") } + +toolbar-next-unread-label = { COPY(from_path, "nextButtonToolbarItem.label") } + +toolbar-next-unread = + .title = { COPY(from_path, "nextButton.tooltip") } + +toolbar-next-label = { COPY(from_path, "nextMsgButton.label") } + +toolbar-next = + .title = { COPY(from_path, "nextMsgButton.tooltip") } + +toolbar-compact-label = { COPY(from_path, "compactButton.label") } + +toolbar-compact = + .title = { COPY(from_path, "compactButton.tooltip") } + +toolbar-tag-message-label = { COPY(from_path, "tagButton.label") } + +toolbar-tag-message = + .title = { COPY(from_path, "tagButton.tooltip") } + +toolbar-forward-inline-label = { COPY(from_path, "forwardButton.label") } + +toolbar-forward-inline = + .title = { COPY(from_path, "forwardAsInline.tooltip") } + +toolbar-forward-attachment-label = { COPY(from_path, "buttonMenuForwardAsAttachment.label") } + +toolbar-forward-attachment = + .title = { COPY(from_path, "forwardAsAttachment.tooltip") } + +toolbar-mark-as-label = { COPY(from_path, "markButton.label") } + +toolbar-mark-as = + .title = { COPY(from_path, "markButton.tooltip") } + +toolbar-address-book-label = { COPY(from_path, "addressBookButton.title") } + +toolbar-address-book = + .title = { COPY(from_path, "addressBookButton.tooltip") } + +toolbar-chat-label = { COPY(from_path, "chatButton.label") } + +toolbar-chat = + .title = { COPY(from_path, "chatButton.tooltip") } + +toolbar-print-label = { COPY(from_path, "printButton.label") } + +toolbar-print = + .title = { COPY(from_path, "printButton.tooltip") } + """, + from_path="mail/chrome/messenger/messenger.dtd", + ), + ) + ctx.add_transforms( + "mail/messenger/unifiedToolbarItems.ftl", + "mail/messenger/unifiedToolbarItems.ftl", + transforms_from( + """ +toolbar-unifinder-label = { COPY(from_path, "showUnifinderCmd.label") } + +toolbar-unifinder = + .title = { COPY(from_path, "showUnifinderCmd.tooltip") } + """, + from_path="calendar/chrome/calendar/menuOverlay.dtd", + ), + ) + ctx.add_transforms( + "mail/messenger/unifiedToolbarItems.ftl", + "mail/messenger/unifiedToolbarItems.ftl", + transforms_from( + """ +toolbar-edit-event-label = { COPY(from_path, "lightning.toolbar.edit.label") } + +toolbar-edit-event = + .title = { COPY(from_path, "lightning.toolbar.edit.tooltip") } + +toolbar-calendar-label = { COPY(from_path, "lightning.toolbar.calendar.label") } + +toolbar-calendar = + .title = { COPY(from_path, "lightning.toolbar.calendar.tooltip") } + +toolbar-tasks-label = { COPY(from_path, "lightning.toolbar.task.label") } + +toolbar-tasks = + .title = { COPY(from_path, "lightning.toolbar.task.tooltip") } + """, + from_path="calendar/chrome/lightning/lightning-toolbar.dtd", + ), + ) + ctx.add_transforms( + "mail/messenger/unifiedToolbarItems.ftl", + "mail/messenger/unifiedToolbarItems.ftl", + transforms_from( + """ +toolbar-redirect-label = { COPY_PATTERN(from_path, "redirect-msg-button.label") } + +toolbar-redirect = + .title = { COPY_PATTERN(from_path, "redirect-msg-button.tooltiptext") } + +toolbar-add-ons-and-themes-label = { COPY_PATTERN(from_path, "addons-and-themes-toolbarbutton.label") } + +toolbar-add-ons-and-themes = + .title = { COPY_PATTERN(from_path, "addons-and-themes-toolbarbutton.tooltiptext") } + + +toolbar-quick-filter-bar-label = { COPY_PATTERN(from_path, "quick-filter-toolbarbutton.label") } + +toolbar-quick-filter-bar = + .title = { COPY_PATTERN(from_path, "quick-filter-toolbarbutton.tooltiptext") } + """, + from_path="mail/messenger/messenger.ftl", + ), + ) + ctx.add_transforms( + "mail/messenger/unifiedToolbarItems.ftl", + "mail/messenger/unifiedToolbarItems.ftl", + transforms_from( + """ +toolbar-junk-label = { COPY_PATTERN(from_path, "toolbar-junk-button.label") } + +toolbar-junk = + .title = { COPY_PATTERN(from_path, "toolbar-junk-button.tooltiptext") } + +toolbar-delete-label = { COPY_PATTERN(from_path, "toolbar-delete-button.label") } + +toolbar-delete = + .title = { COPY_PATTERN(from_path, "toolbar-delete-button.tooltiptext") } + """, + from_path="mail/messenger/menubar.ftl", + ), + ) + ctx.add_transforms( + "mail/messenger/unifiedToolbarItems.ftl", + "mail/messenger/unifiedToolbarItems.ftl", + transforms_from( + """ +toolbar-add-as-event-label = { COPY(from_path, "calendar.extract.event.button") } + +toolbar-add-as-event = + .title = { COPY(from_path, "calendar.extract.event.button.tooltip") } + +toolbar-add-as-task-label = { COPY(from_path, "calendar.extract.task.button") } + +toolbar-add-as-task = + .title = { COPY(from_path, "calendar.extract.task.button.tooltip") } + """, + from_path="calendar/chrome/calendar/calendar.dtd", + ), + ) diff --git a/comm/python/l10n/tb_fluent_migrations/completed/bug_1811400_thread_pane_column_picker.py b/comm/python/l10n/tb_fluent_migrations/completed/bug_1811400_thread_pane_column_picker.py new file mode 100644 index 0000000000..925a4cbbb7 --- /dev/null +++ b/comm/python/l10n/tb_fluent_migrations/completed/bug_1811400_thread_pane_column_picker.py @@ -0,0 +1,79 @@ +# Any copyright is dedicated to the Public Domain. +# http://creativecommons.org/publicdomain/zero/1.0/ + +import fluent.syntax.ast as FTL +from fluent.migrate.helpers import VARIABLE_REFERENCE, transforms_from +from fluent.migrate.transforms import REPLACE + + +def migrate(ctx): + """Bug 1811400 - Migrate thread pane strings, part {index}.""" + + ctx.add_transforms( + "mail/messenger/about3Pane.ftl", + "mail/messenger/about3Pane.ftl", + transforms_from( + """ +apply-columns-to-menu = + .label = { COPY(from_path, "columnPicker.applyTo.label") } + +apply-current-view-to-folder = + .label = { COPY(from_path, "columnPicker.applyToFolder.label") } + +apply-current-view-to-folder-children = + .label = { COPY(from_path, "columnPicker.applyToFolderAndChildren.label") } + """, + from_path="mail/chrome/messenger/messenger.dtd", + ), + ) + ctx.add_transforms( + "mail/messenger/about3Pane.ftl", + "mail/messenger/about3Pane.ftl", + transforms_from( + """ +apply-current-view-to-menu = + .label = { COPY_PATTERN(from_path, "apply-current-view-to-menu.label") } + +apply-changes-to-folder-title = { + COPY_PATTERN(from_path, "threadpane-apply-changes-prompt-title") +} + +apply-current-view-to-folder-message = { + COPY_PATTERN(from_path, "threadpane-apply-changes-prompt-no-children-text") +} + +apply-current-view-to-folder-with-children-message = { + COPY_PATTERN(from_path, "threadpane-apply-changes-prompt-with-children-text") +} + """, + from_path="mail/messenger/mailWidgets.ftl", + ), + ) + ctx.add_transforms( + "mail/messenger/about3Pane.ftl", + "mail/messenger/about3Pane.ftl", + [ + FTL.Message( + id=FTL.Identifier("apply-current-columns-to-folder-message"), + value=REPLACE( + "mail/chrome/messenger/messenger.properties", + "threadPane.columnPicker.confirmFolder.noChildren.message", + { + "%1$S": VARIABLE_REFERENCE("name"), + }, + normalize_printf=True, + ), + ), + FTL.Message( + id=FTL.Identifier("apply-current-columns-to-folder-with-children-message"), + value=REPLACE( + "mail/chrome/messenger/messenger.properties", + "threadPane.columnPicker.confirmFolder.withChildren.message", + { + "%1$S": VARIABLE_REFERENCE("name"), + }, + normalize_printf=True, + ), + ), + ], + ) diff --git a/comm/python/l10n/tb_fluent_migrations/completed/bug_1814393_unified_toolbar_customization_tabs.py b/comm/python/l10n/tb_fluent_migrations/completed/bug_1814393_unified_toolbar_customization_tabs.py new file mode 100644 index 0000000000..5f4c3b469b --- /dev/null +++ b/comm/python/l10n/tb_fluent_migrations/completed/bug_1814393_unified_toolbar_customization_tabs.py @@ -0,0 +1,36 @@ +# Any copyright is dedicated to the Public Domain. +# http://creativecommons.org/publicdomain/zero/1.0/ + +from fluent.migrate import COPY_PATTERN +from fluent.migrate.helpers import transforms_from + + +def migrate(ctx): + """Bug 1814393 - Unified toolbar customization tab titles part {index}.""" + + ctx.add_transforms( + "mail/messenger/unifiedToolbar.ftl", + "mail/messenger/unifiedToolbar.ftl", + transforms_from( + """ +customize-space-tab-mail = { COPY_PATTERN(from_path, "customize-space-mail") } + .title = { COPY_PATTERN(from_path, "customize-space-mail") } + +customize-space-tab-addressbook = { COPY_PATTERN(from_path, "customize-space-addressbook") } + .title = { COPY_PATTERN(from_path, "customize-space-addressbook") } + +customize-space-tab-calendar = { COPY_PATTERN(from_path, "customize-space-calendar") } + .title = { COPY_PATTERN(from_path, "customize-space-calendar") } + +customize-space-tab-tasks = { COPY_PATTERN(from_path, "customize-space-tasks") } + .title = { COPY_PATTERN(from_path, "customize-space-tasks") } + +customize-space-tab-chat = { COPY_PATTERN(from_path, "customize-space-chat") } + .title = { COPY_PATTERN(from_path, "customize-space-chat") } + +customize-space-tab-settings = { COPY_PATTERN(from_path, "customize-space-settings") } + .title = { COPY_PATTERN(from_path, "customize-space-settings") } + """, + from_path="mail/messenger/unifiedToolbar.ftl", + ), + ) diff --git a/comm/python/l10n/tb_fluent_migrations/completed/bug_1814664_unified_toolbar_calendar_items.py b/comm/python/l10n/tb_fluent_migrations/completed/bug_1814664_unified_toolbar_calendar_items.py new file mode 100644 index 0000000000..5985124c42 --- /dev/null +++ b/comm/python/l10n/tb_fluent_migrations/completed/bug_1814664_unified_toolbar_calendar_items.py @@ -0,0 +1,48 @@ +# Any copyright is dedicated to the Public Domain. +# http://creativecommons.org/publicdomain/zero/1.0/ + +from fluent.migrate import COPY_PATTERN +from fluent.migrate.helpers import transforms_from + + +def migrate(ctx): + """Bug 1814664 - Add calendar items to unified toolbar fluent migration part {index}.""" + + ctx.add_transforms( + "mail/messenger/unifiedToolbarItems.ftl", + "mail/messenger/unifiedToolbarItems.ftl", + transforms_from( + """ +toolbar-synchronize-label = { COPY(from_path, "lightning.toolbar.sync.label") } + +toolbar-synchronize = + .title = { COPY(from_path, "lightning.toolbar.sync.tooltip") } + +toolbar-delete-event-label = { COPY(from_path, "lightning.toolbar.delete.label") } + +toolbar-delete-event = + .title = { COPY(from_path, "lightning.toolbar.delete.tooltip") } + +toolbar-go-to-today-label = { COPY(from_path, "lightning.toolbar.gototoday.label") } + +toolbar-go-to-today = + .title = { COPY(from_path, "lightning.toolbar.gototoday.tooltip") } + +toolbar-print-event-label = { COPY(from_path, "lightning.toolbar.print.label") } + +toolbar-print-event = + .title = { COPY(from_path, "lightning.toolbar.print.tooltip") } + +toolbar-new-event-label = { COPY(from_path, "lightning.toolbar.newevent.label") } + +toolbar-new-event = + .title = { COPY(from_path, "lightning.toolbar.newevent.tooltip") } + +toolbar-new-task-label = { COPY(from_path, "lightning.toolbar.newtask.label") } + +toolbar-new-task = + .title = { COPY(from_path, "lightning.toolbar.newtask.tooltip") } + """, + from_path="calendar/chrome/lightning/lightning-toolbar.dtd", + ), + ) diff --git a/comm/python/l10n/tb_fluent_migrations/completed/bug_1815489_add_back_forward_and_stop.py b/comm/python/l10n/tb_fluent_migrations/completed/bug_1815489_add_back_forward_and_stop.py new file mode 100644 index 0000000000..8dab08d9ab --- /dev/null +++ b/comm/python/l10n/tb_fluent_migrations/completed/bug_1815489_add_back_forward_and_stop.py @@ -0,0 +1,33 @@ +# Any copyright is dedicated to the Public Domain. +# http://creativecommons.org/publicdomain/zero/1.0/ + +from fluent.migratetb import COPY +from fluent.migratetb.helpers import transforms_from + + +def migrate(ctx): + """Bug 1815489 - Add back, forward and stop to unified toolbar fluent migration part {index}.""" + + ctx.add_transforms( + "mail/messenger/unifiedToolbarItems.ftl", + "mail/messenger/unifiedToolbarItems.ftl", + transforms_from( + """ +toolbar-go-back-label = { COPY(from_path, "backButton1.label") } + +toolbar-go-back = + .title = { COPY(from_path, "goBackButton.tooltip") } + +toolbar-go-forward-label = { COPY(from_path, "goForwardButton1.label") } + +toolbar-go-forward = + .title = { COPY(from_path, "goForwardButton.tooltip") } + +toolbar-stop-label = { COPY(from_path, "stopButton.label") } + +toolbar-stop = + .title = { COPY(from_path, "stopButton.tooltip") } + """, + from_path="mail/chrome/messenger/messenger.dtd", + ), + ) diff --git a/comm/python/l10n/tb_fluent_migrations/completed/bug_1815605_calendar_context_menu_has_empty_items.py b/comm/python/l10n/tb_fluent_migrations/completed/bug_1815605_calendar_context_menu_has_empty_items.py new file mode 100644 index 0000000000..de0157ac47 --- /dev/null +++ b/comm/python/l10n/tb_fluent_migrations/completed/bug_1815605_calendar_context_menu_has_empty_items.py @@ -0,0 +1,52 @@ +# coding=utf8 + +# Any copyright is dedicated to the Public Domain. +# http://creativecommons.org/publicdomain/zero/1.0/ + +from fluent.migrate.helpers import transforms_from +from fluent.migrate import COPY + + +def migrate(ctx): + """Bug 1815605 - calendar context menu has empty items, part {index}.""" + + ctx.add_transforms( + "calendar/calendar/calendar-widgets.ftl", + "calendar/calendar/calendar-widgets.ftl", + transforms_from( + """ +calendar-context-menu-previous-day = + .label = { COPY(from_path, "calendar.prevday.label") } + .accesskey = { COPY(from_path, "calendar.prevday.accesskey") } + +calendar-context-menu-previous-week = + .label = { COPY(from_path, "calendar.prevweek.label") } + .accesskey = { COPY(from_path, "calendar.prevweek.accesskey") } + +calendar-context-menu-previous-multiweek = + .label = { COPY(from_path, "calendar.prevweek.label") } + .accesskey = { COPY(from_path, "calendar.prevweek.accesskey") } + +calendar-context-menu-previous-month = + .label = { COPY(from_path, "calendar.prevmonth.label") } + .accesskey = { COPY(from_path, "calendar.prevmonth.accesskey") } + +calendar-context-menu-next-day = + .label = { COPY(from_path, "calendar.nextday.label") } + .accesskey = { COPY(from_path, "calendar.nextday.accesskey") } + +calendar-context-menu-next-week = + .label = { COPY(from_path, "calendar.nextweek.label") } + .accesskey = { COPY(from_path, "calendar.nextweek.accesskey") } + +calendar-context-menu-next-multiweek = + .label = { COPY(from_path, "calendar.nextweek.label") } + .accesskey = { COPY(from_path, "calendar.nextweek.accesskey") } + +calendar-context-menu-next-month = + .label = { COPY(from_path, "calendar.nextmonth.label") } + .accesskey = { COPY(from_path, "calendar.nextmonth.accesskey") } +""", + from_path="calendar/chrome/calendar/calendar.dtd", + ), + ) diff --git a/comm/python/l10n/tb_fluent_migrations/completed/bug_1816532_about_dialog_migration.py b/comm/python/l10n/tb_fluent_migrations/completed/bug_1816532_about_dialog_migration.py new file mode 100644 index 0000000000..cc47261099 --- /dev/null +++ b/comm/python/l10n/tb_fluent_migrations/completed/bug_1816532_about_dialog_migration.py @@ -0,0 +1,94 @@ +# coding=utf8 + +# Any copyright is dedicated to the Public Domain. +# http://creativecommons.org/publicdomain/zero/1.0/ + + +from fluent.migratetb.helpers import TERM_REFERENCE +from fluent.migratetb.helpers import transforms_from + + +# This can't just be a straight up literal dict (eg: {"a":"b"}) because the +# validator fails... so make it a function call that returns a dict.. it works +about_replacements = dict( + { + "&brandShorterName;": TERM_REFERENCE("brand-shorter-name"), + "&brandShortName;": TERM_REFERENCE("brand-short-name"), + "&vendorShortName;": TERM_REFERENCE("vendor-short-name"), + } +) + + +def migrate(ctx): + """Bug 1816532 - Migrate aboutDialog.dtd strings to Fluent, part {index}""" + target = reference = "mail/messenger/aboutDialog.ftl" + source = "mail/chrome/messenger/aboutDialog.dtd" + + ctx.add_transforms( + target, + reference, + transforms_from( + """ +release-notes-link = { COPY(source, "releaseNotes.link") } + +update-check-for-updates-button = { COPY(source, "update.checkForUpdatesButton.label") } + .accesskey = { COPY(source, "update.checkForUpdatesButton.accesskey") } + +update-update-button = { REPLACE(source, "update.updateButton.label3", about_replacements) } + .accesskey = { COPY(source, "update.updateButton.accesskey") } + +update-checking-for-updates = { COPY(source, "update.checkingForUpdates") } + +update-downloading-message = { COPY(source, "update.downloading.start") } + +update-applying = { COPY(source, "update.applying") } + +update-downloading = { COPY(source, "update.downloading.start") } + +update-failed = { COPY(source, "update.failed.start") }{ COPY(source, "update.failed.linkText") } + +update-admin-disabled = { COPY(source, "update.adminDisabled") } + +update-no-updates-found = { REPLACE(source, "update.noUpdatesFound", about_replacements) } + +update-other-instance-handling-updates = { REPLACE(source, "update.otherInstanceHandlingUpdates", about_replacements) } + +update-unsupported = { COPY(source, "update.unsupported.start") }{ COPY(source, "update.unsupported.linkText") } + +update-restarting = { COPY(source, "update.restarting") } + +channel-description = { COPY(source, "channel.description.start") }{ $channel } { COPY(source, "channel.description.end", trim: "True") } + +warning-desc-version = { REPLACE(source, "warningDesc.version", about_replacements) } + +warning-desc-telemetry = { REPLACE(source, "warningDesc.telemetryDesc", about_replacements) } + +community-exp = + { REPLACE(source, "community.exp.mozillaLink", about_replacements) } + { COPY(source, "community.exp.middle") } + { COPY(source, "community.exp.creditsLink") } + { COPY(source, "community.exp.end") } + +community-2 = { REPLACE(source, "community.start2", about_replacements) } + { REPLACE(source, "community.mozillaLink", about_replacements) } + { COPY(source, "community.middle2") } + { COPY(source, "community.creditsLink") } + { COPY(source, "community.end3") } + +about-helpus = { COPY(source, "helpus.start") } + { COPY(source, "helpus.donateLink") } or + { COPY(source, "helpus.getInvolvedLink") } + +bottom-links-license = { COPY(source, "bottomLinks.license") } + +bottom-links-rights = { COPY(source, "bottomLinks.rights") } + +bottom-links-privacy = { COPY(source, "bottomLinks.privacy") } + +cmd-close-mac-command-key = + .key = { COPY(source, "cmdCloseMac.commandKey") } +""", + source=source, + about_replacements=about_replacements, + ), + ) diff --git a/comm/python/l10n/tb_fluent_migrations/completed/bug_1816593_flexbox_emulation_dialogs.py b/comm/python/l10n/tb_fluent_migrations/completed/bug_1816593_flexbox_emulation_dialogs.py new file mode 100644 index 0000000000..a920b9c0fd --- /dev/null +++ b/comm/python/l10n/tb_fluent_migrations/completed/bug_1816593_flexbox_emulation_dialogs.py @@ -0,0 +1,21 @@ +# Any copyright is dedicated to the Public Domain. +# http://creativecommons.org/publicdomain/zero/1.0/ + +from fluent.migrate import COPY_PATTERN +from fluent.migrate.helpers import transforms_from + + +def migrate(ctx): + """Bug 1816593 - Fix wrong sized dialogs due to flexbox emulation, part {index}""" + + ctx.add_transforms( + "mail/messenger/compactFoldersDialog.ftl", + "mail/messenger/compactFoldersDialog.ftl", + transforms_from( + """ +compact-dialog-window-title = + .title = {{COPY_PATTERN(from_path, "compact-dialog-window.title")}} + """, + from_path="mail/messenger/compactFoldersDialog.ftl", + ), + ) diff --git a/comm/python/l10n/tb_fluent_migrations/completed/bug_1817914_tags_mode.py b/comm/python/l10n/tb_fluent_migrations/completed/bug_1817914_tags_mode.py new file mode 100644 index 0000000000..d8b3c80d0c --- /dev/null +++ b/comm/python/l10n/tb_fluent_migrations/completed/bug_1817914_tags_mode.py @@ -0,0 +1,21 @@ +# Any copyright is dedicated to the Public Domain. +# http://creativecommons.org/publicdomain/zero/1.0/ + +from fluent.migratetb.helpers import transforms_from + + +def migrate(ctx): + """Bug 1820700 - Implement a Tags folder pane mode, part {index}.""" + + ctx.add_transforms( + "mail/messenger/messenger.ftl", + "mail/messenger/messenger.ftl", + transforms_from( + """ +show-tags-folders-label = + .label = {COPY(from_path, "viewTags.label")} + .accesskey = {COPY(from_path, "viewTags.accesskey")} +""", + from_path="mail/chrome/messenger/msgViewPickerOverlay.dtd", + ), + ) diff --git a/comm/python/l10n/tb_fluent_migrations/completed/bug_1817915_get_new_messages.py b/comm/python/l10n/tb_fluent_migrations/completed/bug_1817915_get_new_messages.py new file mode 100644 index 0000000000..2e2c1ac497 --- /dev/null +++ b/comm/python/l10n/tb_fluent_migrations/completed/bug_1817915_get_new_messages.py @@ -0,0 +1,22 @@ +# Any copyright is dedicated to the Public Domain. +# http://creativecommons.org/publicdomain/zero/1.0/ + +from fluent.migratetb.helpers import transforms_from +from fluent.migratetb import COPY + + +def migrate(ctx): + """Bug 1817915 - Add context menu to Get Messages folder pane button to fetch all messages or per account, part {index}.""" + + ctx.add_transforms( + "mail/messenger/about3Pane.ftl", + "mail/messenger/about3Pane.ftl", + transforms_from( + """ +folder-pane-get-all-messages-menuitem = + .label = { COPY(from_path, "getAllNewMsgCmd.label") } + .accesskey = { COPY(from_path, "getAllNewMsgCmd.accesskey") } + """, + from_path="mail/chrome/messenger/messenger.dtd", + ), + ) diff --git a/comm/python/l10n/tb_fluent_migrations/completed/bug_1820700_select_thread.py b/comm/python/l10n/tb_fluent_migrations/completed/bug_1820700_select_thread.py new file mode 100644 index 0000000000..ae65f694d1 --- /dev/null +++ b/comm/python/l10n/tb_fluent_migrations/completed/bug_1820700_select_thread.py @@ -0,0 +1,35 @@ +# 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 https://mozilla.org/MPL/2.0/. + +# Any copyright is dedicated to the Public Domain. +# http://creativecommons.org/publicdomain/zero/1.0/ + +import fluent.syntax.ast as FTL +from fluent.migratetb.helpers import VARIABLE_REFERENCE, transforms_from +from fluent.migratetb.transforms import REPLACE + + +def migrate(ctx): + """Bug 1820700 - Migrate thread img strings to button, part {index}.""" + + ctx.add_transforms( + "mail/messenger/treeView.ftl", + "mail/messenger/treeView.ftl", + transforms_from( + """ +tree-list-view-row-thread-button = + .title = {COPY_PATTERN(from_path, "tree-list-view-row-thread-icon.title")} + +tree-list-view-row-ignored-thread-button = + .title = {COPY_PATTERN(from_path, "tree-list-view-row-ignored-thread-icon.title")} + +tree-list-view-row-ignored-subthread-button = + .title = {COPY_PATTERN(from_path, "tree-list-view-row-ignored-subthread-icon.title")} + +tree-list-view-row-watched-thread-button = + .title = {COPY_PATTERN(from_path, "tree-list-view-row-watched-thread-icon.title")} +""", + from_path="mail/messenger/treeView.ftl", + ), + ) diff --git a/comm/python/l10n/tb_fluent_migrations/completed/bug_1823033_activity_indicator.py b/comm/python/l10n/tb_fluent_migrations/completed/bug_1823033_activity_indicator.py new file mode 100644 index 0000000000..4cfaec4695 --- /dev/null +++ b/comm/python/l10n/tb_fluent_migrations/completed/bug_1823033_activity_indicator.py @@ -0,0 +1,23 @@ +# Any copyright is dedicated to the Public Domain. +# http://creativecommons.org/publicdomain/zero/1.0/ + +from fluent.migratetb import COPY +from fluent.migratetb.helpers import transforms_from + + +def migrate(ctx): + """Bug 1823033 - Add activity indicator to unified toolbar fluent migration part {index}.""" + + ctx.add_transforms( + "mail/messenger/unifiedToolbarItems.ftl", + "mail/messenger/unifiedToolbarItems.ftl", + transforms_from( + """ +toolbar-throbber-label = { COPY(from_path, "throbberItem.title") } + +toolbar-throbber = + .title = { COPY(from_path, "throbberItem.title") } + """, + from_path="mail/chrome/messenger/messenger.dtd", + ), + ) diff --git a/comm/python/l10n/tb_fluent_migrations/completed/bug_1827261_add_enable_disable_compact_mode_options_to_folder_mode_context_menu.py b/comm/python/l10n/tb_fluent_migrations/completed/bug_1827261_add_enable_disable_compact_mode_options_to_folder_mode_context_menu.py new file mode 100644 index 0000000000..7ea090e903 --- /dev/null +++ b/comm/python/l10n/tb_fluent_migrations/completed/bug_1827261_add_enable_disable_compact_mode_options_to_folder_mode_context_menu.py @@ -0,0 +1,26 @@ +# 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 https://mozilla.org/MPL/2.0/. + +# Any copyright is dedicated to the Public Domain. +# http://creativecommons.org/publicdomain/zero/1.0/ + +from fluent.migratetb.helpers import transforms_from +from fluent.migratetb import COPY + + +def migrate(ctx): + """Bug 1827261 - Add enable/disable compact mode options to Folder Mode context menu, part {index}.""" + + ctx.add_transforms( + "mail/messenger/about3Pane.ftl", + "mail/messenger/about3Pane.ftl", + transforms_from( + """ +folder-pane-mode-context-toggle-compact-mode = + .label = { COPY(from_path, "compactVersion.label") } + .accesskey = { COPY(from_path, "compactVersion.accesskey") } + """, + from_path="mail/chrome/messenger/messenger.dtd", + ), + ) diff --git a/comm/python/l10n/tb_fluent_migrations/completed/bug_1827891_dnt_prefs_learn_more.py b/comm/python/l10n/tb_fluent_migrations/completed/bug_1827891_dnt_prefs_learn_more.py new file mode 100644 index 0000000000..4861e428bc --- /dev/null +++ b/comm/python/l10n/tb_fluent_migrations/completed/bug_1827891_dnt_prefs_learn_more.py @@ -0,0 +1,21 @@ +# Any copyright is dedicated to the Public Domain. +# http://creativecommons.org/publicdomain/zero/1.0/ + +from fluent.migratetb import COPY_PATTERN +from fluent.migratetb.helpers import transforms_from + + +def migrate(ctx): + """Bug 1827891 - DNT Prefs 'learn more' link fix, part {index}.""" + + ctx.add_transforms( + "mail/messenger/preferences/preferences.ftl", + "mail/messenger/preferences/preferences.ftl", + transforms_from( + """ +dnt-learn-more-button = + .value = {{ COPY_PATTERN(from_path, "learn-button.label") }} + """, + from_path="mail/messenger/preferences/preferences.ftl", + ), + ) diff --git a/comm/python/l10n/tb_fluent_migrations/completed/bug_1828340_aboutdialog_layout_fixes.py b/comm/python/l10n/tb_fluent_migrations/completed/bug_1828340_aboutdialog_layout_fixes.py new file mode 100644 index 0000000000..d162e94659 --- /dev/null +++ b/comm/python/l10n/tb_fluent_migrations/completed/bug_1828340_aboutdialog_layout_fixes.py @@ -0,0 +1,42 @@ +# Any copyright is dedicated to the Public Domain. +# http://creativecommons.org/publicdomain/zero/1.0/ + +import re + +from fluent.migratetb import COPY_PATTERN +from fluent.migratetb.transforms import TransformPattern + +import fluent.syntax.ast as FTL + + +class STRIP_NEWLINES(TransformPattern): + def visit_TextElement(self, node): + node.value = re.sub("\n", "", node.value) + return node + + +def migrate(ctx): + """Bug 1828340 - Fix aboutDialog layout issues, part {index}.""" + path = "mail/messenger/aboutDialog.ftl" + ctx.add_transforms( + path, + path, + [ + FTL.Message( + id=FTL.Identifier("about-dialog-title"), + value=COPY_PATTERN(path, "aboutDialog-title.title"), + ), + FTL.Message( + id=FTL.Identifier("community-experimental"), + value=STRIP_NEWLINES(path, "community-exp"), + ), + FTL.Message( + id=FTL.Identifier("community-desc"), + value=STRIP_NEWLINES(path, "community-2"), + ), + FTL.Message( + id=FTL.Identifier("about-donation"), + value=STRIP_NEWLINES(path, "about-helpus"), + ), + ], + ) diff --git a/comm/python/l10n/tb_fluent_migrations/completed/bug_1830004_folder_quota.py b/comm/python/l10n/tb_fluent_migrations/completed/bug_1830004_folder_quota.py new file mode 100644 index 0000000000..07f4505912 --- /dev/null +++ b/comm/python/l10n/tb_fluent_migrations/completed/bug_1830004_folder_quota.py @@ -0,0 +1,28 @@ +# Any copyright is dedicated to the Public Domain. +# http://creativecommons.org/publicdomain/zero/1.0/ + +import fluent.syntax.ast as FTL +from fluent.migratetb.helpers import VARIABLE_REFERENCE, transforms_from +from fluent.migratetb.transforms import REPLACE + + +def migrate(ctx): + """Bug 1830004 - Migrate a quota string, part {index}.""" + + ctx.add_transforms( + "mail/messenger/folderprops.ftl", + "mail/messenger/folderprops.ftl", + [ + FTL.Message( + id=FTL.Identifier("quota-percent-used"), + value=REPLACE( + "mail/chrome/messenger/messenger.properties", + "quotaPercentUsed", + { + "%1$S": VARIABLE_REFERENCE("percent"), + }, + normalize_printf=True, + ), + ), + ], + ) diff --git a/comm/python/l10n/tb_fluent_migrations/completed/bug_1834662_cal_enable78.py b/comm/python/l10n/tb_fluent_migrations/completed/bug_1834662_cal_enable78.py new file mode 100644 index 0000000000..b3f6c420c6 --- /dev/null +++ b/comm/python/l10n/tb_fluent_migrations/completed/bug_1834662_cal_enable78.py @@ -0,0 +1,30 @@ +# 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 https://mozilla.org/MPL/2.0/. + +# Any copyright is dedicated to the Public Domain. +# http://creativecommons.org/publicdomain/zero/1.0/ + +import fluent.syntax.ast as FTL +from fluent.migratetb.helpers import VARIABLE_REFERENCE, transforms_from +from fluent.migratetb.transforms import REPLACE +from fluent.migratetb.transforms import COPY + + +def migrate(ctx): + """Bug 1834662 - Migrate calendar enable button, part {index}.""" + target = reference = "calendar/calendar/calendar-widgets.ftl" + + ctx.add_transforms( + target, + reference, + [ + FTL.Message( + id=FTL.Identifier("calendar-enable-button"), + value=COPY( + "mail/chrome/messenger/addons.properties", + "webextPerms.sideloadEnable.label", + ), + ), + ], + ) diff --git a/comm/python/l10n/tb_fluent_migrations/completed/bug_1834662_extensions_to_fluent.py b/comm/python/l10n/tb_fluent_migrations/completed/bug_1834662_extensions_to_fluent.py new file mode 100644 index 0000000000..cdd8736b67 --- /dev/null +++ b/comm/python/l10n/tb_fluent_migrations/completed/bug_1834662_extensions_to_fluent.py @@ -0,0 +1,531 @@ +# Any copyright is dedicated to the Public Domain. +# http://creativecommons.org/publicdomain/zero/1.0/ + +import fluent.syntax.ast as FTL +from fluent.migratetb.helpers import TERM_REFERENCE, VARIABLE_REFERENCE +from fluent.migratetb.transforms import ( + COPY, + COPY_PATTERN, + PLURALS, + REPLACE, + REPLACE_IN_TEXT, +) + + +def migrate(ctx): + """Bug 1834662 - Migrate addon/extension stuff, part {index}.""" + + # extensionPermissions.ftl - from addons.properties + ctx.add_transforms( + "mail/messenger/extensionPermissions.ftl", + "mail/messenger/extensionPermissions.ftl", + [ + FTL.Message( + id=FTL.Identifier("webext-perms-description-accountsFolders"), + value=COPY( + "mail/chrome/messenger/addons.properties", + "webextPerms.description.accountsFolders", + ), + ), + FTL.Message( + id=FTL.Identifier("webext-perms-description-accountsIdentities"), + value=COPY( + "mail/chrome/messenger/addons.properties", + "webextPerms.description.accountsIdentities", + ), + ), + FTL.Message( + id=FTL.Identifier("webext-perms-description-accountsRead"), + value=COPY( + "mail/chrome/messenger/addons.properties", + "webextPerms.description.accountsRead2", + ), + ), + FTL.Message( + id=FTL.Identifier("webext-perms-description-addressBooks"), + value=COPY( + "mail/chrome/messenger/addons.properties", + "webextPerms.description.addressBooks", + ), + ), + FTL.Message( + id=FTL.Identifier("webext-perms-description-compose"), + value=COPY( + "mail/chrome/messenger/addons.properties", + "webextPerms.description.compose", + ), + ), + FTL.Message( + id=FTL.Identifier("webext-perms-description-compose"), + value=COPY( + "mail/chrome/messenger/addons.properties", + "webextPerms.description.compose", + ), + ), + FTL.Message( + id=FTL.Identifier("webext-perms-description-compose-send"), + value=COPY( + "mail/chrome/messenger/addons.properties", + "webextPerms.description.compose.send", + ), + ), + FTL.Message( + id=FTL.Identifier("webext-perms-description-compose-save"), + value=COPY( + "mail/chrome/messenger/addons.properties", + "webextPerms.description.compose.save", + ), + ), + FTL.Message( + id=FTL.Identifier("webext-perms-description-experiment"), + value=REPLACE( + "mail/chrome/messenger/addons.properties", + "webextPerms.description.experiment", + {"%1$S": TERM_REFERENCE("brand-short-name")}, + ), + ), + FTL.Message( + id=FTL.Identifier("webext-perms-description-messagesImport"), + value=COPY( + "mail/chrome/messenger/addons.properties", + "webextPerms.description.messagesImport", + ), + ), + FTL.Message( + id=FTL.Identifier("webext-perms-description-messagesModify"), + value=COPY( + "mail/chrome/messenger/addons.properties", + "webextPerms.description.messagesModify", + ), + ), + FTL.Message( + id=FTL.Identifier("webext-perms-description-messagesMove"), + value=COPY( + "mail/chrome/messenger/addons.properties", + "webextPerms.description.messagesMove2", + ), + ), + FTL.Message( + id=FTL.Identifier("webext-perms-description-messagesDelete"), + value=COPY( + "mail/chrome/messenger/addons.properties", + "webextPerms.description.messagesDelete", + ), + ), + FTL.Message( + id=FTL.Identifier("webext-perms-description-messagesRead"), + value=COPY( + "mail/chrome/messenger/addons.properties", + "webextPerms.description.messagesRead", + ), + ), + FTL.Message( + id=FTL.Identifier("webext-perms-description-messagesTags"), + value=COPY( + "mail/chrome/messenger/addons.properties", + "webextPerms.description.messagesTags", + ), + ), + FTL.Message( + id=FTL.Identifier("webext-perms-description-sensitiveDataUpload"), + value=COPY( + "mail/chrome/messenger/addons.properties", + "webextPerms.description.sensitiveDataUpload", + ), + ), + ], + ) + + # extensionsUI.ftl - from here and there + ctx.add_transforms( + "mail/messenger/extensionsUI.ftl", + "mail/messenger/extensionsUI.ftl", + [ + FTL.Message( + id=FTL.Identifier("webext-experiment-warning"), + value=COPY( + "mail/chrome/messenger/addons.properties", + "webextPerms.experimentWarning", + ), + ), + FTL.Message( + id=FTL.Identifier("webext-perms-learn-more"), + value=COPY("mail/chrome/messenger/addons.properties", "webextPerms.learnMore2"), + ), + ], + ) + + # addonNotifications.ftl - copied from browser/ migration script + + addons_properties = "mail/chrome/messenger/addons.properties" + notifications = "mail/messenger/addonNotifications.ftl" + + ctx.add_transforms( + notifications, + notifications, + [ + FTL.Message( + id=FTL.Identifier("xpinstall-prompt"), + value=REPLACE( + addons_properties, + "xpinstallPromptMessage", + {"%1$S": TERM_REFERENCE("brand-short-name")}, + ), + ), + FTL.Message( + id=FTL.Identifier("xpinstall-prompt-header"), + value=REPLACE( + addons_properties, + "xpinstallPromptMessage.header", + {"%1$S": VARIABLE_REFERENCE("host")}, + ), + ), + FTL.Message( + id=FTL.Identifier("xpinstall-prompt-message"), + value=REPLACE( + addons_properties, + "xpinstallPromptMessage.message", + {"%1$S": VARIABLE_REFERENCE("host")}, + ), + ), + FTL.Message( + id=FTL.Identifier("xpinstall-prompt-header-unknown"), + value=COPY(addons_properties, "xpinstallPromptMessage.header.unknown"), + ), + FTL.Message( + id=FTL.Identifier("xpinstall-prompt-message-unknown"), + value=COPY(addons_properties, "xpinstallPromptMessage.message.unknown"), + ), + FTL.Message( + id=FTL.Identifier("xpinstall-prompt-dont-allow"), + attributes=[ + FTL.Attribute( + id=FTL.Identifier("label"), + value=COPY(addons_properties, "xpinstallPromptMessage.dontAllow"), + ), + FTL.Attribute( + id=FTL.Identifier("accesskey"), + value=COPY( + addons_properties, + "xpinstallPromptMessage.dontAllow.accesskey", + ), + ), + ], + ), + FTL.Message( + id=FTL.Identifier("xpinstall-prompt-never-allow"), + attributes=[ + FTL.Attribute( + id=FTL.Identifier("label"), + value=COPY(addons_properties, "xpinstallPromptMessage.neverAllow"), + ), + FTL.Attribute( + id=FTL.Identifier("accesskey"), + value=COPY( + addons_properties, + "xpinstallPromptMessage.neverAllow.accesskey", + ), + ), + ], + ), + FTL.Message( + id=FTL.Identifier("xpinstall-prompt-never-allow-and-report"), + attributes=[ + FTL.Attribute( + id=FTL.Identifier("label"), + value=COPY( + addons_properties, + "xpinstallPromptMessage.neverAllowAndReport", + ), + ), + FTL.Attribute( + id=FTL.Identifier("accesskey"), + value=COPY( + addons_properties, + "xpinstallPromptMessage.neverAllowAndReport.accesskey", + ), + ), + ], + ), + FTL.Message( + id=FTL.Identifier("site-permission-install-first-prompt-midi-header"), + value=COPY(addons_properties, "sitePermissionInstallFirstPrompt.midi.header"), + ), + FTL.Message( + id=FTL.Identifier("site-permission-install-first-prompt-midi-message"), + value=COPY(addons_properties, "sitePermissionInstallFirstPrompt.midi.message"), + ), + FTL.Message( + id=FTL.Identifier("xpinstall-prompt-install"), + attributes=[ + FTL.Attribute( + id=FTL.Identifier("label"), + value=COPY(addons_properties, "xpinstallPromptMessage.install"), + ), + FTL.Attribute( + id=FTL.Identifier("accesskey"), + value=COPY( + addons_properties, + "xpinstallPromptMessage.install.accesskey", + ), + ), + ], + ), + FTL.Message( + id=FTL.Identifier("xpinstall-disabled-locked"), + value=COPY(addons_properties, "xpinstallDisabledMessageLocked"), + ), + FTL.Message( + id=FTL.Identifier("xpinstall-disabled"), + value=COPY(addons_properties, "xpinstallDisabledMessage"), + ), + FTL.Message( + id=FTL.Identifier("xpinstall-disabled-button"), + attributes=[ + FTL.Attribute( + id=FTL.Identifier("label"), + value=COPY(addons_properties, "xpinstallDisabledButton"), + ), + FTL.Attribute( + id=FTL.Identifier("accesskey"), + value=COPY(addons_properties, "xpinstallDisabledButton.accesskey"), + ), + ], + ), + FTL.Message( + id=FTL.Identifier("addon-install-blocked-by-policy"), + value=REPLACE( + addons_properties, + "addonInstallBlockedByPolicy", + { + "%1$S": VARIABLE_REFERENCE("addonName"), + "%2$S": VARIABLE_REFERENCE("addonId"), + "%3$S": FTL.TextElement(""), + }, + ), + ), + FTL.Message( + id=FTL.Identifier("addon-domain-blocked-by-policy"), + value=COPY(addons_properties, "addonDomainBlockedByPolicy"), + ), + FTL.Message( + id=FTL.Identifier("addon-install-full-screen-blocked"), + value=COPY(addons_properties, "addonInstallFullScreenBlocked"), + ), + FTL.Message( + id=FTL.Identifier("webext-perms-sideload-menu-item"), + value=REPLACE( + addons_properties, + "webextPerms.sideloadMenuItem", + { + "%1$S": VARIABLE_REFERENCE("addonName"), + "%2$S": TERM_REFERENCE("brand-short-name"), + }, + ), + ), + FTL.Message( + id=FTL.Identifier("webext-perms-update-menu-item"), + value=REPLACE( + addons_properties, + "webextPerms.updateMenuItem", + {"%1$S": VARIABLE_REFERENCE("addonName")}, + ), + ), + FTL.Message( + id=FTL.Identifier("addon-removal-message"), + value=REPLACE( + addons_properties, + "webext.remove.confirmation.message", + { + "%1$S": VARIABLE_REFERENCE("name"), + "%2$S": TERM_REFERENCE("brand-shorter-name"), + }, + ), + ), + FTL.Message( + id=FTL.Identifier("addon-removal-button"), + value=COPY(addons_properties, "webext.remove.confirmation.button"), + ), + FTL.Message( + id=FTL.Identifier("addon-downloading-and-verifying"), + value=PLURALS( + addons_properties, + "addonDownloadingAndVerifying", + VARIABLE_REFERENCE("addonCount"), + foreach=lambda n: REPLACE_IN_TEXT( + n, + {"#1": VARIABLE_REFERENCE("addonCount")}, + ), + ), + ), + FTL.Message( + id=FTL.Identifier("addon-download-verifying"), + value=COPY(addons_properties, "addonDownloadVerifying"), + ), + FTL.Message( + id=FTL.Identifier("addon-install-cancel-button"), + attributes=[ + FTL.Attribute( + id=FTL.Identifier("label"), + value=COPY(addons_properties, "addonInstall.cancelButton.label"), + ), + FTL.Attribute( + id=FTL.Identifier("accesskey"), + value=COPY(addons_properties, "addonInstall.cancelButton.accesskey"), + ), + ], + ), + FTL.Message( + id=FTL.Identifier("addon-install-accept-button"), + attributes=[ + FTL.Attribute( + id=FTL.Identifier("label"), + value=COPY(addons_properties, "addonInstall.acceptButton2.label"), + ), + FTL.Attribute( + id=FTL.Identifier("accesskey"), + value=COPY(addons_properties, "addonInstall.acceptButton2.accesskey"), + ), + ], + ), + FTL.Message( + id=FTL.Identifier("addon-confirm-install-message"), + value=PLURALS( + addons_properties, + "addonConfirmInstall.message", + VARIABLE_REFERENCE("addonCount"), + foreach=lambda n: REPLACE_IN_TEXT( + n, + { + "#1": TERM_REFERENCE("brand-short-name"), + "#2": VARIABLE_REFERENCE("addonCount"), + }, + ), + ), + ), + FTL.Message( + id=FTL.Identifier("addon-confirm-install-unsigned-message"), + value=PLURALS( + addons_properties, + "addonConfirmInstallUnsigned.message", + VARIABLE_REFERENCE("addonCount"), + foreach=lambda n: REPLACE_IN_TEXT( + n, + { + "#1": TERM_REFERENCE("brand-short-name"), + "#2": VARIABLE_REFERENCE("addonCount"), + }, + ), + ), + ), + FTL.Message( + id=FTL.Identifier("addon-confirm-install-some-unsigned-message"), + value=PLURALS( + addons_properties, + "addonConfirmInstallSomeUnsigned.message", + VARIABLE_REFERENCE("addonCount"), + foreach=lambda n: REPLACE_IN_TEXT( + n, + { + "#1": TERM_REFERENCE("brand-short-name"), + "#2": VARIABLE_REFERENCE("addonCount"), + }, + ), + ), + ), + FTL.Message( + id=FTL.Identifier("addon-install-error-network-failure"), + value=COPY(addons_properties, "addonInstallError-1"), + ), + FTL.Message( + id=FTL.Identifier("addon-install-error-incorrect-hash"), + value=REPLACE( + addons_properties, + "addonInstallError-2", + {"%1$S": TERM_REFERENCE("brand-short-name")}, + ), + ), + FTL.Message( + id=FTL.Identifier("addon-install-error-corrupt-file"), + value=COPY(addons_properties, "addonInstallError-3"), + ), + FTL.Message( + id=FTL.Identifier("addon-install-error-file-access"), + value=REPLACE( + addons_properties, + "addonInstallError-4", + { + "%2$S": VARIABLE_REFERENCE("addonName"), + "%1$S": TERM_REFERENCE("brand-short-name"), + }, + ), + ), + FTL.Message( + id=FTL.Identifier("addon-install-error-not-signed"), + value=REPLACE( + addons_properties, + "addonInstallError-5", + {"%1$S": TERM_REFERENCE("brand-short-name")}, + ), + ), + FTL.Message( + id=FTL.Identifier("addon-install-error-invalid-domain"), + value=REPLACE( + addons_properties, + "addonInstallError-8", + {"%2$S": VARIABLE_REFERENCE("addonName")}, + ), + ), + FTL.Message( + id=FTL.Identifier("addon-local-install-error-network-failure"), + value=COPY(addons_properties, "addonLocalInstallError-1"), + ), + FTL.Message( + id=FTL.Identifier("addon-local-install-error-incorrect-hash"), + value=REPLACE( + addons_properties, + "addonLocalInstallError-2", + {"%1$S": TERM_REFERENCE("brand-short-name")}, + ), + ), + FTL.Message( + id=FTL.Identifier("addon-local-install-error-corrupt-file"), + value=COPY(addons_properties, "addonLocalInstallError-3"), + ), + FTL.Message( + id=FTL.Identifier("addon-local-install-error-file-access"), + value=REPLACE( + addons_properties, + "addonLocalInstallError-4", + { + "%2$S": VARIABLE_REFERENCE("addonName"), + "%1$S": TERM_REFERENCE("brand-short-name"), + }, + ), + ), + FTL.Message( + id=FTL.Identifier("addon-local-install-error-not-signed"), + value=COPY(addons_properties, "addonLocalInstallError-5"), + ), + FTL.Message( + id=FTL.Identifier("addon-install-error-incompatible"), + value=REPLACE( + addons_properties, + "addonInstallErrorIncompatible", + { + "%3$S": VARIABLE_REFERENCE("addonName"), + "%1$S": TERM_REFERENCE("brand-short-name"), + "%2$S": VARIABLE_REFERENCE("appVersion"), + }, + ), + ), + FTL.Message( + id=FTL.Identifier("addon-install-error-blocklisted"), + value=REPLACE( + addons_properties, + "addonInstallErrorBlocklisted", + {"%1$S": VARIABLE_REFERENCE("addonName")}, + ), + ), + ], + ) diff --git a/comm/python/l10n/tbxchannel/__init__.py b/comm/python/l10n/tbxchannel/__init__.py new file mode 100644 index 0000000000..b6599032bc --- /dev/null +++ b/comm/python/l10n/tbxchannel/__init__.py @@ -0,0 +1,47 @@ +# 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 pathlib import Path + +from .l10n_merge import COMM_STRINGS_QUARANTINE, COMM_STRINGS_QUARANTINE_PUSH + +TB_XC_NOTIFICATION_TMPL = """\ +**Thunderbird L10n Cross Channel** + +Changes pushed to `comm-strings-quarantine`: {rev_url} +""" + + +def get_thunderbird_xc_config(topsrcdir, strings_path): + assert isinstance(topsrcdir, Path) + assert isinstance(strings_path, Path) + return { + "strings": { + "path": strings_path, + "url": COMM_STRINGS_QUARANTINE, + "heads": {"default": "default"}, + "update_on_pull": True, + "push_url": COMM_STRINGS_QUARANTINE_PUSH, + }, + "source": { + "comm-central": { + "path": topsrcdir / "comm", + "url": "https://hg.mozilla.org/comm-central/", + "heads": { + # This list of repositories is ordered, starting with the + # one with the most recent content (central) to the oldest + # (ESR). In case two ESR versions are supported, the oldest + # ESR goes last (e.g. esr102 goes after esr115). + "comm": "comm-central", + "comm-beta": "releases/comm-beta", + "comm-esr102": "releases/comm-esr102", + }, + "config_files": [ + "comm/calendar/locales/l10n.toml", + "comm/mail/locales/l10n.toml", + "comm/suite/locales/l10n.toml", + ], + }, + }, + } diff --git a/comm/python/l10n/tbxchannel/l10n_merge.py b/comm/python/l10n/tbxchannel/l10n_merge.py new file mode 100644 index 0000000000..b202e7dfe0 --- /dev/null +++ b/comm/python/l10n/tbxchannel/l10n_merge.py @@ -0,0 +1,26 @@ +# 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/. + +L10N_CENTRAL = "https://hg.mozilla.org/l10n-central" +COMM_L10N = "https://hg.mozilla.org/projects/comm-l10n" +COMM_L10N_PUSH = f"ssh{COMM_L10N[5:]}" +COMM_STRINGS_QUARANTINE = "https://hg.mozilla.org/projects/comm-strings-quarantine" +COMM_STRINGS_QUARANTINE_PUSH = f"ssh{COMM_STRINGS_QUARANTINE[5:]}" + + +GECKO_STRINGS_PATTERNS = ( + "{lang}/browser/pdfviewer/**", + "{lang}/devtools/**", + "{lang}/dom/**", + "{lang}/extensions/spellcheck/**", + "{lang}/netwerk/**", + "{lang}/security/**", + "{lang}/toolkit/**", +) + +COMM_STRINGS_PATTERNS = ( + "{lang}/calendar/**", + "{lang}/chat/**", + "{lang}/mail/**", +) diff --git a/comm/python/l10n/tbxchannel/quarantine_to_strings.py b/comm/python/l10n/tbxchannel/quarantine_to_strings.py new file mode 100644 index 0000000000..def3f59e5e --- /dev/null +++ b/comm/python/l10n/tbxchannel/quarantine_to_strings.py @@ -0,0 +1,194 @@ +# 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 https://mozilla.org/MPL/2.0/. + +import logging +import os +import shutil +import subprocess +import tempfile +from pathlib import Path + +from typing_extensions import Literal + +from mozversioncontrol import HgRepository +from mozversioncontrol.repoupdate import update_mercurial_repo + +from .l10n_merge import COMM_L10N, COMM_L10N_PUSH, COMM_STRINGS_QUARANTINE + +ACTIONS = Literal["clean", "prep", "migrate", "push"] + + +class HgL10nRepository(HgRepository): + log_trans_table = str.maketrans({"{": "{{", "}": "}}"}) + + def __init__(self, path: Path, check_url=None, logger=print): + super(HgL10nRepository, self).__init__(path, hg="hg") + self._logger = logger + if check_url is not None: + self._check_hg_url(check_url) + + def logger(self, *args): + # Escape python-style format string substitutions because Sentry is annoying + self._logger(*args[:-1], args[-1].translate(self.log_trans_table)) + + def _check_hg_url(self, repo_url): + configured_url = self._run("config", "paths.default").strip() + if configured_url != repo_url: + raise Exception(f"Repository does not match {repo_url}.") + + def check_status(self): + if not self.working_directory_clean() or self.get_outgoing_files(): + raise Exception(f"Repository at {self.path} is not clean, run with 'clean'.") + + def last_convert_rev(self): + args = ( + "log", + "-r", + "last(extra('convert_source', 'comm-strings-quarantine'))", + "--template", + "{get(extras,'convert_revision')}\n", + ) + self.logger(logging.INFO, "last_convert_rev", {}, " ".join(args)) + rv = self._run(*args).strip() + self.logger(logging.INFO, "last_convert_rev", {}, rv) + return rv + + def next_convert_rev(self, last_converted): + args = ("log", "-r", f"first(children({last_converted}))", "--template", "{node}\n") + self.logger(logging.INFO, "next_convert_rev", {}, " ".join(args)) + rv = self._run(*args).strip() + self.logger(logging.INFO, "next_convert_rev", {}, rv) + return rv + + def convert_quarantine(self, strings_path, filemap_path, splicemap_path, next_converted_rev): + args = ( + "convert", + "--config", + "convert.hg.saverev=True", + "--config", + "convert.hg.sourcename=comm-strings-quarantine", + "--config", + f"convert.hg.revs={next_converted_rev}:tip", + "--filemap", + filemap_path, + "--splicemap", + splicemap_path, + "--datesort", + str(self.path), + str(strings_path.absolute()), + ) + self.logger(logging.INFO, "convert_quarantine", {}, " ".join(args)) + rv = self._run(*args) + self.logger(logging.INFO, "convert_quarantine", {}, rv) + return rv + + def push(self, push_url): + popen_kwargs = { + "stdout": subprocess.PIPE, + "stderr": subprocess.PIPE, + "cwd": self.path, + "env": self._env, + "universal_newlines": True, + "bufsize": 1, + } + cmd = ("hg", "push", "-r", ".", push_url) + self.logger(logging.INFO, "push", {}, " ".join(cmd)) + # This function doesn't really push to try... + self._push_to_try_with_log_capture(cmd, popen_kwargs) + + +def _nuke_hg_repos(*paths: Path): + failed = {} + for path in paths: + try: + if path.exists(): + shutil.rmtree(str(path)) + except Exception as e: + failed[str(path)] = e + + if failed: + for f in failed: + print(f"Unable to nuke '{f}': {failed[f]}") + raise Exception() + + +def publish_strings( + command_context, + quarantine_path: Path, + comm_l10n_path: Path, + actions: ACTIONS, + **kwargs, +): + if "clean" in actions: + command_context.log(logging.INFO, "clean", {}, "Removing old repository clones.") + _nuke_hg_repos(quarantine_path, comm_l10n_path) + + if "prep" in actions: + # update_mercurial_repo also will clone if a repo is not already there + command_context.log( + logging.INFO, "prep", {}, f"Updating comm-strings-quarantine at {quarantine_path}." + ) + update_mercurial_repo("hg", COMM_STRINGS_QUARANTINE, quarantine_path) + command_context.log(logging.INFO, "prep", {}, f"Updating comm-l10n at {comm_l10n_path}.") + update_mercurial_repo("hg", COMM_L10N, comm_l10n_path) + + local_quarantine = HgL10nRepository( + quarantine_path, COMM_STRINGS_QUARANTINE, command_context.log + ) + local_comm_l10n = HgL10nRepository(comm_l10n_path, COMM_L10N, command_context.log) + + if "prep" not in actions: + local_quarantine.update("tip") + local_comm_l10n.update("tip") + + if "migrate" in actions: + local_quarantine.check_status() + local_comm_l10n.check_status() + + command_context.log( + logging.INFO, "migrate", {}, "Starting string migration from quarantine." + ) + head_rev = local_comm_l10n.head_ref + last_convert_rev = local_comm_l10n.last_convert_rev() + first_convert_rev = local_quarantine.next_convert_rev(last_convert_rev) + command_context.log( + logging.INFO, "migrate", {}, f" Last converted rev: {last_convert_rev}" + ) + command_context.log( + logging.INFO, "migrate", {}, f" First converted rev: {first_convert_rev}" + ) + + with tempfile.NamedTemporaryFile( + prefix="splicemap", suffix=".txt", delete=False + ) as splice_fp: + splicemap = splice_fp.name + command_context.log( + logging.INFO, "migrate", {}, f" Writing splicemap to: {splicemap}" + ) + splice_fp.write(f"{first_convert_rev} {head_rev}\n".encode("utf-8")) + + with tempfile.NamedTemporaryFile(prefix="filemap", suffix=".txt", delete=False) as file_fp: + filemap = file_fp.name + command_context.log(logging.INFO, "migrate", {}, f" Writing filemap to: {filemap}") + file_fp.writelines( + ["exclude _configs\n".encode("utf-8"), "rename . en-US\n".encode("utf-8")] + ) + + command_context.log(logging.INFO, "migrate", {}, " Running hg convert...") + local_quarantine.convert_quarantine(comm_l10n_path, filemap, splicemap, first_convert_rev) + try: + os.unlink(splicemap) + os.unlink(filemap) + except Exception: + pass + + local_comm_l10n.update("tip") + command_context.log(logging.INFO, "migrate", {}, " Finished!") + + if "push" in actions: + if local_comm_l10n.get_outgoing_files(): + command_context.log(logging.INFO, "push", {}, " Pushing to comm-l10n.") + local_comm_l10n.push(COMM_L10N_PUSH) + else: + command_context.log(logging.INFO, "push", {}, "Skipping empty push.") diff --git a/comm/python/l10n/tbxchannel/tb_migration_test.py b/comm/python/l10n/tbxchannel/tb_migration_test.py new file mode 100644 index 0000000000..8e01e1d889 --- /dev/null +++ b/comm/python/l10n/tbxchannel/tb_migration_test.py @@ -0,0 +1,172 @@ +# 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/. +""" +Test comm-l10n Fluent migrations +""" + +import logging +import os +import re +import shutil + +import hglib +from compare_locales.merge import merge_channels +from compare_locales.paths.configparser import TOMLParser +from compare_locales.paths.files import ProjectFiles +from fluent.migratetb import validator +from test_fluent_migrations.fmt import diff_resources + +import mozpack.path as mozpath +from mach.util import get_state_dir +from mozversioncontrol.repoupdate import update_mercurial_repo + +from .l10n_merge import COMM_L10N + + +def inspect_migration(path): + """Validate recipe and extract some metadata.""" + return validator.Validator.validate(path) + + +def prepare_object_dir(cmd): + """Prepare object dir to have an up-to-date clone of comm-l10n. + + We run this once per mach invocation, for all tested migrations. + """ + obj_dir = mozpath.join(cmd.topobjdir, "comm", "python", "l10n") + if not os.path.exists(obj_dir): + os.makedirs(obj_dir) + state_dir = get_state_dir() + update_mercurial_repo("hg", COMM_L10N, mozpath.join(state_dir, "comm-strings")) + return obj_dir + + +def test_migration(cmd, obj_dir, to_test, references): + """Test the given recipe. + + This creates a workdir by merging comm-strings-quarantine and the c-c source, + to mimic comm-strings-quarantine after the patch to test landed. + It then runs the recipe with a comm-strings-quarantine clone as localization, both + dry and wet. + It inspects the generated commits, and shows a diff between the merged + reference and the generated content. + The diff is intended to be visually inspected. Some changes might be + expected, in particular when formatting of the en-US strings is different. + """ + rv = 0 + migration_name = os.path.splitext(os.path.split(to_test)[1])[0] + l10n_lib = os.path.abspath(os.path.dirname(os.path.dirname(to_test))) + work_dir = mozpath.join(obj_dir, migration_name) + + paths = os.path.normpath(to_test).split(os.sep) + # Migration modules should be in a sub-folder of l10n. + migration_module = ".".join(paths[paths.index("l10n") + 1 : -1]) + "." + migration_name + + if os.path.exists(work_dir): + shutil.rmtree(work_dir) + os.makedirs(mozpath.join(work_dir, "reference")) + l10n_toml = mozpath.join(cmd.topsrcdir, cmd.substs["MOZ_BUILD_APP"], "locales", "l10n.toml") + pc = TOMLParser().parse(l10n_toml, env={"l10n_base": work_dir}) + pc.set_locales(["reference"]) + files = ProjectFiles("reference", [pc]) + for ref in references: + if ref != mozpath.normpath(ref): + cmd.log( + logging.ERROR, + "tb-fluent-migration-test", + { + "file": to_test, + "ref": ref, + }, + 'Reference path "{ref}" needs to be normalized for {file}', + ) + rv = 1 + continue + full_ref = mozpath.join(work_dir, "reference", ref) + m = files.match(full_ref) + if m is None: + raise ValueError(f"Bad reference path: {ref} - {full_ref}") + m_c_path = m[1] + g_s_path = mozpath.join(work_dir, "comm-strings", ref) + resources = [ + b"" if not os.path.exists(f) else open(f, "rb").read() for f in (g_s_path, m_c_path) + ] + ref_dir = os.path.dirname(full_ref) + if not os.path.exists(ref_dir): + os.makedirs(ref_dir) + open(full_ref, "wb").write(merge_channels(ref, resources)) + client = hglib.clone( + source=mozpath.join(get_state_dir(), "comm-strings"), + dest=mozpath.join(work_dir, "comm-strings"), + ) + client.open() + old_tip = client.tip().node + run_migration = [ + cmd._virtualenv_manager.python_path, + "-m", + "fluent.migratetb.tool", + "--locale", + "en-US", + "--reference-dir", + mozpath.join(work_dir, "reference"), + "--localization-dir", + mozpath.join(work_dir, "comm-strings"), + "--dry-run", + migration_module, + ] + append_env = {"PYTHONPATH": l10n_lib} + cmd.run_process( + run_migration, + append_env=append_env, + cwd=work_dir, + line_handler=print, + ) + # drop --dry-run + run_migration.pop(-2) + cmd.run_process( + run_migration, + append_env=append_env, + cwd=work_dir, + line_handler=print, + ) + tip = client.tip().node + if old_tip == tip: + cmd.log( + logging.WARN, + "tb-fluent-migration-test", + { + "file": to_test, + }, + "No migration applied for {file}", + ) + return rv + for ref in references: + diff_resources( + mozpath.join(work_dir, "reference", ref), + mozpath.join(work_dir, "comm-strings", "en-US", ref), + ) + messages = [l.desc.decode("utf-8") for l in client.log(b"::%s - ::%s" % (tip, old_tip))] + bug = re.search("[0-9]{5,}", migration_name) + # Just check first message for bug number, they're all following the same pattern + if bug is None or bug.group() not in messages[0]: + rv = 1 + cmd.log( + logging.ERROR, + "tb-fluent-migration-test", + { + "file": to_test, + }, + "Missing or wrong bug number for {file}", + ) + if any("part {}".format(n + 1) not in msg for n, msg in enumerate(messages)): + rv = 1 + cmd.log( + logging.ERROR, + "tb-fluent-migration-test", + { + "file": to_test, + }, + 'Commit messages should have "part {{index}}" for {file}', + ) + return rv -- cgit v1.2.3