summaryrefslogtreecommitdiffstats
path: root/python/l10n/fluent_migrations
diff options
context:
space:
mode:
Diffstat (limited to 'python/l10n/fluent_migrations')
-rw-r--r--python/l10n/fluent_migrations/__init__.py0
-rw-r--r--python/l10n/fluent_migrations/bug_1552333_aboutCertError.py40
-rw-r--r--python/l10n/fluent_migrations/bug_1635548_browser_context.py82
-rw-r--r--python/l10n/fluent_migrations/bug_1738056_aboutDialog_channel.py33
-rw-r--r--python/l10n/fluent_migrations/bug_1786186_mobile_aboutConfig.py65
-rw-r--r--python/l10n/fluent_migrations/bug_1793557_extensions.py912
-rw-r--r--python/l10n/fluent_migrations/bug_1793572_webrtc.py771
-rw-r--r--python/l10n/fluent_migrations/bug_1813077_popup_notification_learn_more.py22
-rw-r--r--python/l10n/fluent_migrations/bug_1814261_mixed_content_identity_panel.py49
-rw-r--r--python/l10n/fluent_migrations/bug_1814266_identity_custom_root.py34
-rw-r--r--python/l10n/fluent_migrations/bug_1818322_mozTabList.py26
-rw-r--r--python/l10n/fluent_migrations/bug_1820654_update_manual.py30
-rw-r--r--python/l10n/fluent_migrations/bug_1821187_migrationWizard_password_file_import_strings.py27
-rw-r--r--python/l10n/fluent_migrations/bug_1821779_migrationWizard_browser_names.py38
-rw-r--r--python/l10n/fluent_migrations/bug_1828443_pocket_policy.py30
-rw-r--r--python/l10n/fluent_migrations/bug_1828767_sanitize_dialog_native_size.py77
-rw-r--r--python/l10n/fluent_migrations/bug_1830042_places.py127
-rw-r--r--python/l10n/fluent_migrations/bug_1831851_accounts.py195
-rw-r--r--python/l10n/fluent_migrations/bug_1831872_sync.py31
-rw-r--r--python/l10n/fluent_migrations/bug_1832138_ctrlTab.py37
-rw-r--r--python/l10n/fluent_migrations/bug_1832141_recently_closed.py76
-rw-r--r--python/l10n/fluent_migrations/bug_1832179_sendTabToDevice.py37
-rw-r--r--python/l10n/fluent_migrations/bug_1832186_popupwarning.py139
-rw-r--r--python/l10n/fluent_migrations/bug_1832668_firefoxView_navigation.py27
-rw-r--r--python/l10n/fluent_migrations/bug_1833228_fxviewTabList.py44
-rw-r--r--python/l10n/fluent_migrations/bug_1835559_aboutDialog_explicit_textContent.py67
-rw-r--r--python/l10n/fluent_migrations/bug_1866295_new_device_migration_strings.py22
-rw-r--r--python/l10n/fluent_migrations/bug_1867346_new_device_migration_string_replacement.py22
28 files changed, 3060 insertions, 0 deletions
diff --git a/python/l10n/fluent_migrations/__init__.py b/python/l10n/fluent_migrations/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/python/l10n/fluent_migrations/__init__.py
diff --git a/python/l10n/fluent_migrations/bug_1552333_aboutCertError.py b/python/l10n/fluent_migrations/bug_1552333_aboutCertError.py
new file mode 100644
index 0000000000..5c8300e01f
--- /dev/null
+++ b/python/l10n/fluent_migrations/bug_1552333_aboutCertError.py
@@ -0,0 +1,40 @@
+# 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 transforms_from
+from fluent.migrate.helpers import VARIABLE_REFERENCE
+from fluent.migrate import COPY, REPLACE
+
+
+def migrate(ctx):
+ """Bug 1552333 - Migrate strings from pipnss.properties to aboutCertError.ftl"""
+ ctx.add_transforms(
+ "browser/browser/aboutCertError.ftl",
+ "browser/browser/aboutCertError.ftl",
+ transforms_from(
+ """
+cert-error-symantec-distrust-admin = { COPY(from_path, "certErrorSymantecDistrustAdministrator") }
+""",
+ from_path="security/manager/chrome/pipnss/pipnss.properties",
+ ),
+ )
+ ctx.add_transforms(
+ "browser/browser/aboutCertError.ftl",
+ "browser/browser/aboutCertError.ftl",
+ [
+ FTL.Message(
+ id=FTL.Identifier("cert-error-symantec-distrust-description"),
+ value=REPLACE(
+ "security/manager/chrome/pipnss/pipnss.properties",
+ "certErrorSymantecDistrustDescription1",
+ {
+ "%1$S": VARIABLE_REFERENCE("hostname"),
+ },
+ normalize_printf=True,
+ ),
+ ),
+ ],
+ )
diff --git a/python/l10n/fluent_migrations/bug_1635548_browser_context.py b/python/l10n/fluent_migrations/bug_1635548_browser_context.py
new file mode 100644
index 0000000000..33bd0efc95
--- /dev/null
+++ b/python/l10n/fluent_migrations/bug_1635548_browser_context.py
@@ -0,0 +1,82 @@
+# 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 transforms_from, VARIABLE_REFERENCE
+from fluent.migrate import REPLACE, COPY
+
+
+def migrate(ctx):
+ """Bug 1635548 - Migrate browser-context.inc to Fluent, part {index}"""
+ target = "toolkit/toolkit/global/textActions.ftl"
+ reference = "toolkit/toolkit/global/textActions.ftl"
+ ctx.add_transforms(
+ target,
+ reference,
+ transforms_from(
+ """
+text-action-spell-add-to-dictionary =
+ .label = { COPY(from_path, "spellAddToDictionary.label") }
+ .accesskey = { COPY(from_path, "spellAddToDictionary.accesskey") }
+
+text-action-spell-undo-add-to-dictionary =
+ .label = { COPY(from_path, "spellUndoAddToDictionary.label") }
+ .accesskey = { COPY(from_path, "spellUndoAddToDictionary.accesskey") }
+
+text-action-spell-check-toggle =
+ .label = { COPY(from_path, "spellCheckToggle.label") }
+ .accesskey = { COPY(from_path, "spellCheckToggle.accesskey") }
+
+text-action-spell-dictionaries =
+ .label = { COPY(from_path, "spellDictionaries.label") }
+ .accesskey = { COPY(from_path, "spellDictionaries.accesskey") }
+""",
+ from_path="toolkit/chrome/global/textcontext.dtd",
+ ),
+ )
+
+ target = "toolkit/toolkit/global/textActions.ftl"
+ reference = "toolkit/toolkit/global/textActions.ftl"
+ ctx.add_transforms(
+ target,
+ reference,
+ transforms_from(
+ """
+text-action-spell-add-dictionaries =
+ .label = { COPY(from_path, "spellAddDictionaries.label") }
+ .accesskey = { COPY(from_path, "spellAddDictionaries.accesskey") }
+""",
+ from_path="browser/chrome/browser/browser.dtd",
+ ),
+ )
+
+ target = "browser/browser/browserContext.ftl"
+ reference = "browser/browser/browserContext.ftl"
+ ctx.add_transforms(
+ target,
+ reference,
+ [
+ FTL.Message(
+ id=FTL.Identifier("main-context-menu-open-link-in-container-tab"),
+ attributes=[
+ FTL.Attribute(
+ FTL.Identifier("label"),
+ REPLACE(
+ "browser/chrome/browser/browser.properties",
+ "userContextOpenLink.label",
+ {"%1$S": VARIABLE_REFERENCE("containerName")},
+ ),
+ ),
+ FTL.Attribute(
+ FTL.Identifier("accesskey"),
+ COPY(
+ "browser/chrome/browser/browser.dtd",
+ "openLinkCmdInTab.accesskey",
+ ),
+ ),
+ ],
+ )
+ ],
+ )
diff --git a/python/l10n/fluent_migrations/bug_1738056_aboutDialog_channel.py b/python/l10n/fluent_migrations/bug_1738056_aboutDialog_channel.py
new file mode 100644
index 0000000000..b867155ebf
--- /dev/null
+++ b/python/l10n/fluent_migrations/bug_1738056_aboutDialog_channel.py
@@ -0,0 +1,33 @@
+# Any copyright is dedicated to the Public Domain.
+# http://creativecommons.org/publicdomain/zero/1.0/
+
+import fluent.syntax.ast as FTL
+import re
+
+from fluent.migrate.transforms import TransformPattern
+
+
+class INSERT_VARIABLE(TransformPattern):
+ def visit_TextElement(self, node):
+ node.value = re.sub(
+ 'current-channel"></label',
+ 'current-channel">{ $channel }</label',
+ node.value,
+ )
+ return node
+
+
+def migrate(ctx):
+ """Bug 1738056 - Convert about dialog channel listing to fluent, part {index}."""
+
+ about_dialog_ftl = "browser/browser/aboutDialog.ftl"
+ ctx.add_transforms(
+ about_dialog_ftl,
+ about_dialog_ftl,
+ [
+ FTL.Message(
+ id=FTL.Identifier("aboutdialog-channel-description"),
+ value=INSERT_VARIABLE(about_dialog_ftl, "channel-description"),
+ ),
+ ],
+ )
diff --git a/python/l10n/fluent_migrations/bug_1786186_mobile_aboutConfig.py b/python/l10n/fluent_migrations/bug_1786186_mobile_aboutConfig.py
new file mode 100644
index 0000000000..99c6673f92
--- /dev/null
+++ b/python/l10n/fluent_migrations/bug_1786186_mobile_aboutConfig.py
@@ -0,0 +1,65 @@
+# 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 transforms_from
+from fluent.migrate.transforms import COPY
+
+
+def migrate(ctx):
+ """Bug 1786186 - Migrate mobile about:config to Fluent, part {index}"""
+
+ target = "mobile/android/mobile/android/aboutConfig.ftl"
+
+ ctx.add_transforms(
+ target,
+ target,
+ transforms_from(
+ """
+
+config-toolbar-search =
+ .placeholder = { COPY(path1, "toolbar.searchPlaceholder") }
+config-new-pref-name =
+ .placeholder = { COPY(path1, "newPref.namePlaceholder") }
+config-new-pref-value-boolean = { COPY(path1, "newPref.valueBoolean") }
+config-new-pref-value-string = { COPY(path1, "newPref.valueString") }
+config-new-pref-value-integer = { COPY(path1, "newPref.valueInteger") }
+config-new-pref-string =
+ .placeholder = { COPY(path1, "newPref.stringPlaceholder") }
+config-new-pref-number =
+ .placeholder = { COPY(path1, "newPref.numberPlaceholder") }
+config-new-pref-cancel-button = { COPY(path1, "newPref.cancelButton") }
+config-context-menu-copy-pref-name =
+ .label = { COPY(path1, "contextMenu.copyPrefName") }
+config-context-menu-copy-pref-value =
+ .label = { COPY(path1, "contextMenu.copyPrefValue") }
+""",
+ path1="mobile/android/chrome/config.dtd",
+ ),
+ )
+
+ source = "mobile/android/chrome/config.properties"
+ ctx.add_transforms(
+ target,
+ target,
+ [
+ FTL.Message(
+ id=FTL.Identifier("config-new-pref-create-button"),
+ value=COPY(source, "newPref.createButton"),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("config-new-pref-change-button"),
+ value=COPY(source, "newPref.changeButton"),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("config-pref-toggle-button"),
+ value=COPY(source, "pref.toggleButton"),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("config-pref-reset-button"),
+ value=COPY(source, "pref.resetButton"),
+ ),
+ ],
+ )
diff --git a/python/l10n/fluent_migrations/bug_1793557_extensions.py b/python/l10n/fluent_migrations/bug_1793557_extensions.py
new file mode 100644
index 0000000000..0c04a87509
--- /dev/null
+++ b/python/l10n/fluent_migrations/bug_1793557_extensions.py
@@ -0,0 +1,912 @@
+# 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 TERM_REFERENCE, VARIABLE_REFERENCE
+from fluent.migrate.transforms import (
+ COPY,
+ COPY_PATTERN,
+ PLURALS,
+ REPLACE,
+ REPLACE_IN_TEXT,
+)
+
+
+def migrate(ctx):
+ """Bug 1793557 - Convert extension strings to Fluent, part {index}."""
+
+ browser_properties = "browser/chrome/browser/browser.properties"
+ browser_ftl = "browser/browser/browser.ftl"
+ notifications = "browser/browser/addonNotifications.ftl"
+ extensions_ui = "browser/browser/extensionsUI.ftl"
+ extensions = "toolkit/toolkit/global/extensions.ftl"
+ permissions = "toolkit/toolkit/global/extensionPermissions.ftl"
+
+ ctx.add_transforms(
+ browser_ftl,
+ browser_ftl,
+ [
+ FTL.Message(
+ id=FTL.Identifier("popup-notification-addon-install-unsigned"),
+ attributes=[
+ FTL.Attribute(
+ id=FTL.Identifier("value"),
+ value=COPY(browser_properties, "addonInstall.unsigned"),
+ )
+ ],
+ ),
+ ],
+ )
+
+ ctx.add_transforms(
+ notifications,
+ notifications,
+ [
+ FTL.Message(
+ id=FTL.Identifier("xpinstall-prompt"),
+ value=REPLACE(
+ browser_properties,
+ "xpinstallPromptMessage",
+ {"%1$S": TERM_REFERENCE("brand-short-name")},
+ ),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("xpinstall-prompt-header"),
+ value=REPLACE(
+ browser_properties,
+ "xpinstallPromptMessage.header",
+ {"%1$S": VARIABLE_REFERENCE("host")},
+ ),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("xpinstall-prompt-message"),
+ value=REPLACE(
+ browser_properties,
+ "xpinstallPromptMessage.message",
+ {"%1$S": VARIABLE_REFERENCE("host")},
+ ),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("xpinstall-prompt-header-unknown"),
+ value=COPY(browser_properties, "xpinstallPromptMessage.header.unknown"),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("xpinstall-prompt-message-unknown"),
+ value=COPY(
+ browser_properties, "xpinstallPromptMessage.message.unknown"
+ ),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("xpinstall-prompt-dont-allow"),
+ attributes=[
+ FTL.Attribute(
+ id=FTL.Identifier("label"),
+ value=COPY(
+ browser_properties, "xpinstallPromptMessage.dontAllow"
+ ),
+ ),
+ FTL.Attribute(
+ id=FTL.Identifier("accesskey"),
+ value=COPY(
+ browser_properties,
+ "xpinstallPromptMessage.dontAllow.accesskey",
+ ),
+ ),
+ ],
+ ),
+ FTL.Message(
+ id=FTL.Identifier("xpinstall-prompt-never-allow"),
+ attributes=[
+ FTL.Attribute(
+ id=FTL.Identifier("label"),
+ value=COPY(
+ browser_properties, "xpinstallPromptMessage.neverAllow"
+ ),
+ ),
+ FTL.Attribute(
+ id=FTL.Identifier("accesskey"),
+ value=COPY(
+ browser_properties,
+ "xpinstallPromptMessage.neverAllow.accesskey",
+ ),
+ ),
+ ],
+ ),
+ FTL.Message(
+ id=FTL.Identifier("xpinstall-prompt-never-allow-and-report"),
+ attributes=[
+ FTL.Attribute(
+ id=FTL.Identifier("label"),
+ value=COPY(
+ browser_properties,
+ "xpinstallPromptMessage.neverAllowAndReport",
+ ),
+ ),
+ FTL.Attribute(
+ id=FTL.Identifier("accesskey"),
+ value=COPY(
+ browser_properties,
+ "xpinstallPromptMessage.neverAllowAndReport.accesskey",
+ ),
+ ),
+ ],
+ ),
+ FTL.Message(
+ id=FTL.Identifier("site-permission-install-first-prompt-midi-header"),
+ value=COPY(
+ browser_properties, "sitePermissionInstallFirstPrompt.midi.header"
+ ),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("site-permission-install-first-prompt-midi-message"),
+ value=COPY(
+ browser_properties, "sitePermissionInstallFirstPrompt.midi.message"
+ ),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("xpinstall-prompt-install"),
+ attributes=[
+ FTL.Attribute(
+ id=FTL.Identifier("label"),
+ value=COPY(
+ browser_properties, "xpinstallPromptMessage.install"
+ ),
+ ),
+ FTL.Attribute(
+ id=FTL.Identifier("accesskey"),
+ value=COPY(
+ browser_properties,
+ "xpinstallPromptMessage.install.accesskey",
+ ),
+ ),
+ ],
+ ),
+ FTL.Message(
+ id=FTL.Identifier("xpinstall-disabled-locked"),
+ value=COPY(browser_properties, "xpinstallDisabledMessageLocked"),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("xpinstall-disabled"),
+ value=COPY(browser_properties, "xpinstallDisabledMessage"),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("xpinstall-disabled-button"),
+ attributes=[
+ FTL.Attribute(
+ id=FTL.Identifier("label"),
+ value=COPY(browser_properties, "xpinstallDisabledButton"),
+ ),
+ FTL.Attribute(
+ id=FTL.Identifier("accesskey"),
+ value=COPY(
+ browser_properties, "xpinstallDisabledButton.accesskey"
+ ),
+ ),
+ ],
+ ),
+ FTL.Message(
+ id=FTL.Identifier("addon-install-blocked-by-policy"),
+ value=REPLACE(
+ browser_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(browser_properties, "addonDomainBlockedByPolicy"),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("addon-install-full-screen-blocked"),
+ value=COPY(browser_properties, "addonInstallFullScreenBlocked"),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("webext-perms-sideload-menu-item"),
+ value=REPLACE(
+ browser_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(
+ browser_properties,
+ "webextPerms.updateMenuItem",
+ {"%1$S": VARIABLE_REFERENCE("addonName")},
+ ),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("addon-removal-title"),
+ value=COPY_PATTERN(browser_ftl, "addon-removal-title"),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("addon-removal-message"),
+ value=REPLACE(
+ browser_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(browser_properties, "webext.remove.confirmation.button"),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("addon-removal-abuse-report-checkbox"),
+ value=COPY_PATTERN(browser_ftl, "addon-removal-abuse-report-checkbox"),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("addon-downloading-and-verifying"),
+ value=PLURALS(
+ browser_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(browser_properties, "addonDownloadVerifying"),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("addon-install-cancel-button"),
+ attributes=[
+ FTL.Attribute(
+ id=FTL.Identifier("label"),
+ value=COPY(
+ browser_properties, "addonInstall.cancelButton.label"
+ ),
+ ),
+ FTL.Attribute(
+ id=FTL.Identifier("accesskey"),
+ value=COPY(
+ browser_properties, "addonInstall.cancelButton.accesskey"
+ ),
+ ),
+ ],
+ ),
+ FTL.Message(
+ id=FTL.Identifier("addon-install-accept-button"),
+ attributes=[
+ FTL.Attribute(
+ id=FTL.Identifier("label"),
+ value=COPY(
+ browser_properties, "addonInstall.acceptButton2.label"
+ ),
+ ),
+ FTL.Attribute(
+ id=FTL.Identifier("accesskey"),
+ value=COPY(
+ browser_properties, "addonInstall.acceptButton2.accesskey"
+ ),
+ ),
+ ],
+ ),
+ FTL.Message(
+ id=FTL.Identifier("addon-confirm-install-message"),
+ value=PLURALS(
+ browser_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(
+ browser_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(
+ browser_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(browser_properties, "addonInstallError-1"),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("addon-install-error-incorrect-hash"),
+ value=REPLACE(
+ browser_properties,
+ "addonInstallError-2",
+ {"%1$S": TERM_REFERENCE("brand-short-name")},
+ ),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("addon-install-error-corrupt-file"),
+ value=COPY(browser_properties, "addonInstallError-3"),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("addon-install-error-file-access"),
+ value=REPLACE(
+ browser_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(
+ browser_properties,
+ "addonInstallError-5",
+ {"%1$S": TERM_REFERENCE("brand-short-name")},
+ ),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("addon-install-error-invalid-domain"),
+ value=REPLACE(
+ browser_properties,
+ "addonInstallError-8",
+ {"%2$S": VARIABLE_REFERENCE("addonName")},
+ ),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("addon-local-install-error-network-failure"),
+ value=COPY(browser_properties, "addonLocalInstallError-1"),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("addon-local-install-error-incorrect-hash"),
+ value=REPLACE(
+ browser_properties,
+ "addonLocalInstallError-2",
+ {"%1$S": TERM_REFERENCE("brand-short-name")},
+ ),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("addon-local-install-error-corrupt-file"),
+ value=COPY(browser_properties, "addonLocalInstallError-3"),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("addon-local-install-error-file-access"),
+ value=REPLACE(
+ browser_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(browser_properties, "addonLocalInstallError-5"),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("addon-install-error-incompatible"),
+ value=REPLACE(
+ browser_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(
+ browser_properties,
+ "addonInstallErrorBlocklisted",
+ {"%1$S": VARIABLE_REFERENCE("addonName")},
+ ),
+ ),
+ ],
+ )
+
+ ctx.add_transforms(
+ extensions_ui,
+ extensions_ui,
+ [
+ FTL.Message(
+ id=FTL.Identifier("webext-perms-learn-more"),
+ value=COPY(browser_properties, "webextPerms.learnMore2"),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("webext-default-search-description"),
+ value=REPLACE(
+ browser_properties,
+ "webext.defaultSearch.description",
+ {
+ "%1$S": VARIABLE_REFERENCE("addonName"),
+ "%2$S": VARIABLE_REFERENCE("currentEngine"),
+ "%3$S": VARIABLE_REFERENCE("newEngine"),
+ },
+ ),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("webext-default-search-yes"),
+ attributes=[
+ FTL.Attribute(
+ id=FTL.Identifier("label"),
+ value=COPY(browser_properties, "webext.defaultSearchYes.label"),
+ ),
+ FTL.Attribute(
+ id=FTL.Identifier("accesskey"),
+ value=COPY(
+ browser_properties, "webext.defaultSearchYes.accessKey"
+ ),
+ ),
+ ],
+ ),
+ FTL.Message(
+ id=FTL.Identifier("webext-default-search-no"),
+ attributes=[
+ FTL.Attribute(
+ id=FTL.Identifier("label"),
+ value=COPY(browser_properties, "webext.defaultSearchNo.label"),
+ ),
+ FTL.Attribute(
+ id=FTL.Identifier("accesskey"),
+ value=COPY(
+ browser_properties, "webext.defaultSearchNo.accessKey"
+ ),
+ ),
+ ],
+ ),
+ FTL.Message(
+ id=FTL.Identifier("addon-post-install-message"),
+ value=REPLACE(
+ browser_properties,
+ "addonPostInstall.message3",
+ {"%1$S": VARIABLE_REFERENCE("addonName")},
+ ),
+ ),
+ ],
+ )
+
+ ctx.add_transforms(
+ extensions,
+ extensions,
+ [
+ FTL.Message(
+ id=FTL.Identifier("webext-perms-header"),
+ value=REPLACE(
+ browser_properties,
+ "webextPerms.header",
+ {"%1$S": VARIABLE_REFERENCE("extension")},
+ ),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("webext-perms-header-with-perms"),
+ value=REPLACE(
+ browser_properties,
+ "webextPerms.headerWithPerms",
+ {"%1$S": VARIABLE_REFERENCE("extension")},
+ ),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("webext-perms-header-unsigned"),
+ value=REPLACE(
+ browser_properties,
+ "webextPerms.headerUnsigned",
+ {"%1$S": VARIABLE_REFERENCE("extension")},
+ ),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("webext-perms-header-unsigned-with-perms"),
+ value=REPLACE(
+ browser_properties,
+ "webextPerms.headerUnsignedWithPerms",
+ {"%1$S": VARIABLE_REFERENCE("extension")},
+ ),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("webext-perms-add"),
+ attributes=[
+ FTL.Attribute(
+ id=FTL.Identifier("label"),
+ value=COPY(browser_properties, "webextPerms.add.label"),
+ ),
+ FTL.Attribute(
+ id=FTL.Identifier("accesskey"),
+ value=COPY(browser_properties, "webextPerms.add.accessKey"),
+ ),
+ ],
+ ),
+ FTL.Message(
+ id=FTL.Identifier("webext-perms-cancel"),
+ attributes=[
+ FTL.Attribute(
+ id=FTL.Identifier("label"),
+ value=COPY(browser_properties, "webextPerms.cancel.label"),
+ ),
+ FTL.Attribute(
+ id=FTL.Identifier("accesskey"),
+ value=COPY(browser_properties, "webextPerms.cancel.accessKey"),
+ ),
+ ],
+ ),
+ FTL.Message(
+ id=FTL.Identifier("webext-perms-sideload-header"),
+ value=REPLACE(
+ browser_properties,
+ "webextPerms.sideloadHeader",
+ {"%1$S": VARIABLE_REFERENCE("extension")},
+ ),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("webext-perms-sideload-text"),
+ value=COPY(browser_properties, "webextPerms.sideloadText2"),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("webext-perms-sideload-text-no-perms"),
+ value=COPY(browser_properties, "webextPerms.sideloadTextNoPerms"),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("webext-perms-sideload-enable"),
+ attributes=[
+ FTL.Attribute(
+ id=FTL.Identifier("label"),
+ value=COPY(
+ browser_properties, "webextPerms.sideloadEnable.label"
+ ),
+ ),
+ FTL.Attribute(
+ id=FTL.Identifier("accesskey"),
+ value=COPY(
+ browser_properties, "webextPerms.sideloadEnable.accessKey"
+ ),
+ ),
+ ],
+ ),
+ FTL.Message(
+ id=FTL.Identifier("webext-perms-sideload-cancel"),
+ attributes=[
+ FTL.Attribute(
+ id=FTL.Identifier("label"),
+ value=COPY(
+ browser_properties, "webextPerms.sideloadCancel.label"
+ ),
+ ),
+ FTL.Attribute(
+ id=FTL.Identifier("accesskey"),
+ value=COPY(
+ browser_properties, "webextPerms.sideloadCancel.accessKey"
+ ),
+ ),
+ ],
+ ),
+ FTL.Message(
+ id=FTL.Identifier("webext-perms-update-text"),
+ value=REPLACE(
+ browser_properties,
+ "webextPerms.updateText2",
+ {"%1$S": VARIABLE_REFERENCE("extension")},
+ ),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("webext-perms-update-accept"),
+ attributes=[
+ FTL.Attribute(
+ id=FTL.Identifier("label"),
+ value=COPY(
+ browser_properties, "webextPerms.updateAccept.label"
+ ),
+ ),
+ FTL.Attribute(
+ id=FTL.Identifier("accesskey"),
+ value=COPY(
+ browser_properties, "webextPerms.updateAccept.accessKey"
+ ),
+ ),
+ ],
+ ),
+ FTL.Message(
+ id=FTL.Identifier("webext-perms-optional-perms-header"),
+ value=REPLACE(
+ browser_properties,
+ "webextPerms.optionalPermsHeader",
+ {"%1$S": VARIABLE_REFERENCE("extension")},
+ ),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("webext-perms-optional-perms-list-intro"),
+ value=COPY(browser_properties, "webextPerms.optionalPermsListIntro"),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("webext-perms-optional-perms-allow"),
+ attributes=[
+ FTL.Attribute(
+ id=FTL.Identifier("label"),
+ value=COPY(
+ browser_properties, "webextPerms.optionalPermsAllow.label"
+ ),
+ ),
+ FTL.Attribute(
+ id=FTL.Identifier("accesskey"),
+ value=COPY(
+ browser_properties,
+ "webextPerms.optionalPermsAllow.accessKey",
+ ),
+ ),
+ ],
+ ),
+ FTL.Message(
+ id=FTL.Identifier("webext-perms-optional-perms-deny"),
+ attributes=[
+ FTL.Attribute(
+ id=FTL.Identifier("label"),
+ value=COPY(
+ browser_properties, "webextPerms.optionalPermsDeny.label"
+ ),
+ ),
+ FTL.Attribute(
+ id=FTL.Identifier("accesskey"),
+ value=COPY(
+ browser_properties,
+ "webextPerms.optionalPermsDeny.accessKey",
+ ),
+ ),
+ ],
+ ),
+ FTL.Message(
+ id=FTL.Identifier("webext-perms-host-description-all-urls"),
+ value=COPY(browser_properties, "webextPerms.hostDescription.allUrls"),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("webext-perms-host-description-wildcard"),
+ value=REPLACE(
+ browser_properties,
+ "webextPerms.hostDescription.wildcard",
+ {"%1$S": VARIABLE_REFERENCE("domain")},
+ ),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("webext-perms-host-description-too-many-wildcards"),
+ value=PLURALS(
+ browser_properties,
+ "webextPerms.hostDescription.tooManyWildcards",
+ VARIABLE_REFERENCE("domainCount"),
+ foreach=lambda n: REPLACE_IN_TEXT(
+ n,
+ {"#1": VARIABLE_REFERENCE("domainCount")},
+ ),
+ ),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("webext-perms-host-description-one-site"),
+ value=REPLACE(
+ browser_properties,
+ "webextPerms.hostDescription.oneSite",
+ {"%1$S": VARIABLE_REFERENCE("domain")},
+ ),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("webext-perms-host-description-too-many-sites"),
+ value=PLURALS(
+ browser_properties,
+ "webextPerms.hostDescription.tooManySites",
+ VARIABLE_REFERENCE("domainCount"),
+ foreach=lambda n: REPLACE_IN_TEXT(
+ n,
+ {"#1": VARIABLE_REFERENCE("domainCount")},
+ ),
+ ),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("webext-site-perms-header-with-gated-perms-midi"),
+ value=REPLACE(
+ browser_properties,
+ "webextSitePerms.headerWithGatedPerms.midi",
+ {
+ "%1$S": VARIABLE_REFERENCE("hostname"),
+ },
+ ),
+ ),
+ FTL.Message(
+ id=FTL.Identifier(
+ "webext-site-perms-header-with-gated-perms-midi-sysex"
+ ),
+ value=REPLACE(
+ browser_properties,
+ "webextSitePerms.headerWithGatedPerms.midi-sysex",
+ {
+ "%1$S": VARIABLE_REFERENCE("hostname"),
+ },
+ ),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("webext-site-perms-description-gated-perms-midi"),
+ value=COPY(
+ browser_properties, "webextSitePerms.descriptionGatedPerms.midi"
+ ),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("webext-site-perms-header-with-perms"),
+ value=REPLACE(
+ browser_properties,
+ "webextSitePerms.headerWithPerms",
+ {
+ "%1$S": VARIABLE_REFERENCE("extension"),
+ "%2$S": VARIABLE_REFERENCE("hostname"),
+ },
+ ),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("webext-site-perms-header-unsigned-with-perms"),
+ value=REPLACE(
+ browser_properties,
+ "webextSitePerms.headerUnsignedWithPerms",
+ {
+ "%1$S": VARIABLE_REFERENCE("extension"),
+ "%2$S": VARIABLE_REFERENCE("hostname"),
+ },
+ ),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("webext-site-perms-midi"),
+ value=COPY(browser_properties, "webextSitePerms.description.midi"),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("webext-site-perms-midi-sysex"),
+ value=COPY(
+ browser_properties, "webextSitePerms.description.midi-sysex"
+ ),
+ ),
+ ],
+ )
+
+ ctx.add_transforms(
+ permissions,
+ permissions,
+ [
+ FTL.Message(
+ id=FTL.Identifier("webext-perms-description-bookmarks"),
+ value=COPY(browser_properties, "webextPerms.description.bookmarks"),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("webext-perms-description-browserSettings"),
+ value=COPY(
+ browser_properties, "webextPerms.description.browserSettings"
+ ),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("webext-perms-description-browsingData"),
+ value=COPY(browser_properties, "webextPerms.description.browsingData"),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("webext-perms-description-clipboardRead"),
+ value=COPY(browser_properties, "webextPerms.description.clipboardRead"),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("webext-perms-description-clipboardWrite"),
+ value=COPY(
+ browser_properties, "webextPerms.description.clipboardWrite"
+ ),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("webext-perms-description-declarativeNetRequest"),
+ value=COPY(
+ browser_properties, "webextPerms.description.declarativeNetRequest"
+ ),
+ ),
+ FTL.Message(
+ id=FTL.Identifier(
+ "webext-perms-description-declarativeNetRequestFeedback"
+ ),
+ value=COPY(
+ browser_properties,
+ "webextPerms.description.declarativeNetRequestFeedback",
+ ),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("webext-perms-description-devtools"),
+ value=COPY(browser_properties, "webextPerms.description.devtools"),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("webext-perms-description-downloads"),
+ value=COPY(browser_properties, "webextPerms.description.downloads"),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("webext-perms-description-downloads-open"),
+ value=COPY(
+ browser_properties, "webextPerms.description.downloads.open"
+ ),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("webext-perms-description-find"),
+ value=COPY(browser_properties, "webextPerms.description.find"),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("webext-perms-description-geolocation"),
+ value=COPY(browser_properties, "webextPerms.description.geolocation"),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("webext-perms-description-history"),
+ value=COPY(browser_properties, "webextPerms.description.history"),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("webext-perms-description-management"),
+ value=COPY(browser_properties, "webextPerms.description.management"),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("webext-perms-description-nativeMessaging"),
+ value=REPLACE(
+ browser_properties,
+ "webextPerms.description.nativeMessaging",
+ {"%1$S": TERM_REFERENCE("brand-short-name")},
+ ),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("webext-perms-description-notifications"),
+ value=COPY(browser_properties, "webextPerms.description.notifications"),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("webext-perms-description-pkcs11"),
+ value=COPY(browser_properties, "webextPerms.description.pkcs11"),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("webext-perms-description-privacy"),
+ value=COPY(browser_properties, "webextPerms.description.privacy"),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("webext-perms-description-proxy"),
+ value=COPY(browser_properties, "webextPerms.description.proxy"),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("webext-perms-description-sessions"),
+ value=COPY(browser_properties, "webextPerms.description.sessions"),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("webext-perms-description-tabs"),
+ value=COPY(browser_properties, "webextPerms.description.tabs"),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("webext-perms-description-tabHide"),
+ value=COPY(browser_properties, "webextPerms.description.tabHide"),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("webext-perms-description-topSites"),
+ value=COPY(browser_properties, "webextPerms.description.topSites"),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("webext-perms-description-webNavigation"),
+ value=COPY(browser_properties, "webextPerms.description.webNavigation"),
+ ),
+ ],
+ )
diff --git a/python/l10n/fluent_migrations/bug_1793572_webrtc.py b/python/l10n/fluent_migrations/bug_1793572_webrtc.py
new file mode 100644
index 0000000000..eb07f939a8
--- /dev/null
+++ b/python/l10n/fluent_migrations/bug_1793572_webrtc.py
@@ -0,0 +1,771 @@
+# 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 TERM_REFERENCE, VARIABLE_REFERENCE
+from fluent.migrate.transforms import (
+ COPY,
+ COPY_PATTERN,
+ PLURALS,
+ REPLACE,
+ REPLACE_IN_TEXT,
+)
+
+
+def migrate(ctx):
+ """Bug 1793572 - Convert WebRTC strings to Fluent, part {index}."""
+
+ source = "browser/chrome/browser/webrtcIndicator.properties"
+ browser = "browser/chrome/browser/browser.properties"
+ browser_ftl = "browser/browser/browser.ftl"
+ target = "browser/browser/webrtcIndicator.ftl"
+
+ ctx.add_transforms(
+ target,
+ target,
+ [
+ FTL.Message(
+ id=FTL.Identifier("webrtc-indicator-window"),
+ attributes=[
+ FTL.Attribute(
+ id=FTL.Identifier("title"),
+ value=COPY_PATTERN(target, "webrtc-indicator-title"),
+ )
+ ],
+ ),
+ FTL.Message(
+ id=FTL.Identifier("webrtc-indicator-sharing-camera-and-microphone"),
+ attributes=[
+ FTL.Attribute(
+ id=FTL.Identifier("tooltiptext"),
+ value=COPY(
+ source, "webrtcIndicator.sharingCameraAndMicrophone.tooltip"
+ ),
+ )
+ ],
+ ),
+ FTL.Message(
+ id=FTL.Identifier("webrtc-indicator-sharing-camera"),
+ attributes=[
+ FTL.Attribute(
+ id=FTL.Identifier("tooltiptext"),
+ value=COPY(source, "webrtcIndicator.sharingCamera.tooltip"),
+ )
+ ],
+ ),
+ FTL.Message(
+ id=FTL.Identifier("webrtc-indicator-sharing-microphone"),
+ attributes=[
+ FTL.Attribute(
+ id=FTL.Identifier("tooltiptext"),
+ value=COPY(source, "webrtcIndicator.sharingMicrophone.tooltip"),
+ )
+ ],
+ ),
+ FTL.Message(
+ id=FTL.Identifier("webrtc-indicator-sharing-application"),
+ attributes=[
+ FTL.Attribute(
+ id=FTL.Identifier("tooltiptext"),
+ value=COPY(
+ source, "webrtcIndicator.sharingApplication.tooltip"
+ ),
+ )
+ ],
+ ),
+ FTL.Message(
+ id=FTL.Identifier("webrtc-indicator-sharing-screen"),
+ attributes=[
+ FTL.Attribute(
+ id=FTL.Identifier("tooltiptext"),
+ value=COPY(source, "webrtcIndicator.sharingScreen.tooltip"),
+ )
+ ],
+ ),
+ FTL.Message(
+ id=FTL.Identifier("webrtc-indicator-sharing-window"),
+ attributes=[
+ FTL.Attribute(
+ id=FTL.Identifier("tooltiptext"),
+ value=COPY(source, "webrtcIndicator.sharingWindow.tooltip"),
+ )
+ ],
+ ),
+ FTL.Message(
+ id=FTL.Identifier("webrtc-indicator-sharing-browser"),
+ attributes=[
+ FTL.Attribute(
+ id=FTL.Identifier("tooltiptext"),
+ value=COPY(source, "webrtcIndicator.sharingBrowser.tooltip"),
+ )
+ ],
+ ),
+ FTL.Message(
+ id=FTL.Identifier("webrtc-indicator-menuitem-control-sharing"),
+ attributes=[
+ FTL.Attribute(
+ id=FTL.Identifier("label"),
+ value=COPY(source, "webrtcIndicator.controlSharing.menuitem"),
+ )
+ ],
+ ),
+ FTL.Message(
+ id=FTL.Identifier("webrtc-indicator-menuitem-control-sharing-on"),
+ attributes=[
+ FTL.Attribute(
+ id=FTL.Identifier("label"),
+ value=REPLACE(
+ source,
+ "webrtcIndicator.controlSharingOn.menuitem",
+ {"%1$S": VARIABLE_REFERENCE("streamTitle")},
+ ),
+ )
+ ],
+ ),
+ FTL.Message(
+ id=FTL.Identifier("webrtc-indicator-menuitem-sharing-camera-with"),
+ attributes=[
+ FTL.Attribute(
+ id=FTL.Identifier("label"),
+ value=REPLACE(
+ source,
+ "webrtcIndicator.sharingCameraWith.menuitem",
+ {"%1$S": VARIABLE_REFERENCE("streamTitle")},
+ ),
+ )
+ ],
+ ),
+ FTL.Message(
+ id=FTL.Identifier("webrtc-indicator-menuitem-sharing-microphone-with"),
+ attributes=[
+ FTL.Attribute(
+ id=FTL.Identifier("label"),
+ value=REPLACE(
+ source,
+ "webrtcIndicator.sharingMicrophoneWith.menuitem",
+ {"%1$S": VARIABLE_REFERENCE("streamTitle")},
+ ),
+ )
+ ],
+ ),
+ FTL.Message(
+ id=FTL.Identifier("webrtc-indicator-menuitem-sharing-application-with"),
+ attributes=[
+ FTL.Attribute(
+ id=FTL.Identifier("label"),
+ value=REPLACE(
+ source,
+ "webrtcIndicator.sharingApplicationWith.menuitem",
+ {"%1$S": VARIABLE_REFERENCE("streamTitle")},
+ ),
+ )
+ ],
+ ),
+ FTL.Message(
+ id=FTL.Identifier("webrtc-indicator-menuitem-sharing-screen-with"),
+ attributes=[
+ FTL.Attribute(
+ id=FTL.Identifier("label"),
+ value=REPLACE(
+ source,
+ "webrtcIndicator.sharingScreenWith.menuitem",
+ {"%1$S": VARIABLE_REFERENCE("streamTitle")},
+ ),
+ )
+ ],
+ ),
+ FTL.Message(
+ id=FTL.Identifier("webrtc-indicator-menuitem-sharing-window-with"),
+ attributes=[
+ FTL.Attribute(
+ id=FTL.Identifier("label"),
+ value=REPLACE(
+ source,
+ "webrtcIndicator.sharingWindowWith.menuitem",
+ {"%1$S": VARIABLE_REFERENCE("streamTitle")},
+ ),
+ )
+ ],
+ ),
+ FTL.Message(
+ id=FTL.Identifier("webrtc-indicator-menuitem-sharing-browser-with"),
+ attributes=[
+ FTL.Attribute(
+ id=FTL.Identifier("label"),
+ value=REPLACE(
+ source,
+ "webrtcIndicator.sharingBrowserWith.menuitem",
+ {"%1$S": VARIABLE_REFERENCE("streamTitle")},
+ ),
+ )
+ ],
+ ),
+ FTL.Message(
+ id=FTL.Identifier(
+ "webrtc-indicator-menuitem-sharing-camera-with-n-tabs"
+ ),
+ attributes=[
+ FTL.Attribute(
+ id=FTL.Identifier("label"),
+ value=PLURALS(
+ source,
+ "webrtcIndicator.sharingCameraWithNTabs.menuitem",
+ VARIABLE_REFERENCE("tabCount"),
+ foreach=lambda n: REPLACE_IN_TEXT(
+ n,
+ {"#1": VARIABLE_REFERENCE("tabCount")},
+ ),
+ ),
+ )
+ ],
+ ),
+ FTL.Message(
+ id=FTL.Identifier(
+ "webrtc-indicator-menuitem-sharing-microphone-with-n-tabs"
+ ),
+ attributes=[
+ FTL.Attribute(
+ id=FTL.Identifier("label"),
+ value=PLURALS(
+ source,
+ "webrtcIndicator.sharingMicrophoneWithNTabs.menuitem",
+ VARIABLE_REFERENCE("tabCount"),
+ foreach=lambda n: REPLACE_IN_TEXT(
+ n,
+ {"#1": VARIABLE_REFERENCE("tabCount")},
+ ),
+ ),
+ )
+ ],
+ ),
+ FTL.Message(
+ id=FTL.Identifier(
+ "webrtc-indicator-menuitem-sharing-application-with-n-tabs"
+ ),
+ attributes=[
+ FTL.Attribute(
+ id=FTL.Identifier("label"),
+ value=PLURALS(
+ source,
+ "webrtcIndicator.sharingApplicationWithNTabs.menuitem",
+ VARIABLE_REFERENCE("tabCount"),
+ foreach=lambda n: REPLACE_IN_TEXT(
+ n,
+ {"#1": VARIABLE_REFERENCE("tabCount")},
+ ),
+ ),
+ )
+ ],
+ ),
+ FTL.Message(
+ id=FTL.Identifier(
+ "webrtc-indicator-menuitem-sharing-screen-with-n-tabs"
+ ),
+ attributes=[
+ FTL.Attribute(
+ id=FTL.Identifier("label"),
+ value=PLURALS(
+ source,
+ "webrtcIndicator.sharingScreenWithNTabs.menuitem",
+ VARIABLE_REFERENCE("tabCount"),
+ foreach=lambda n: REPLACE_IN_TEXT(
+ n,
+ {"#1": VARIABLE_REFERENCE("tabCount")},
+ ),
+ ),
+ )
+ ],
+ ),
+ FTL.Message(
+ id=FTL.Identifier(
+ "webrtc-indicator-menuitem-sharing-window-with-n-tabs"
+ ),
+ attributes=[
+ FTL.Attribute(
+ id=FTL.Identifier("label"),
+ value=PLURALS(
+ source,
+ "webrtcIndicator.sharingWindowWithNTabs.menuitem",
+ VARIABLE_REFERENCE("tabCount"),
+ foreach=lambda n: REPLACE_IN_TEXT(
+ n,
+ {"#1": VARIABLE_REFERENCE("tabCount")},
+ ),
+ ),
+ )
+ ],
+ ),
+ FTL.Message(
+ id=FTL.Identifier(
+ "webrtc-indicator-menuitem-sharing-browser-with-n-tabs"
+ ),
+ attributes=[
+ FTL.Attribute(
+ id=FTL.Identifier("label"),
+ value=PLURALS(
+ source,
+ "webrtcIndicator.sharingBrowserWithNTabs.menuitem",
+ VARIABLE_REFERENCE("tabCount"),
+ foreach=lambda n: REPLACE_IN_TEXT(
+ n,
+ {"#1": VARIABLE_REFERENCE("tabCount")},
+ ),
+ ),
+ )
+ ],
+ ),
+ FTL.Message(
+ id=FTL.Identifier("webrtc-item-camera"),
+ value=REPLACE(
+ browser,
+ "getUserMedia.sharingMenuCamera",
+ {
+ "%1$S (": FTL.TextElement(""),
+ "%1$S(": FTL.TextElement(""),
+ ")": FTL.TextElement(""),
+ ")": FTL.TextElement(""),
+ },
+ ),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("webrtc-item-microphone"),
+ value=REPLACE(
+ browser,
+ "getUserMedia.sharingMenuMicrophone",
+ {
+ "%1$S (": FTL.TextElement(""),
+ "%1$S(": FTL.TextElement(""),
+ ")": FTL.TextElement(""),
+ ")": FTL.TextElement(""),
+ },
+ ),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("webrtc-item-audio-capture"),
+ value=REPLACE(
+ browser,
+ "getUserMedia.sharingMenuAudioCapture",
+ {
+ "%1$S (": FTL.TextElement(""),
+ "%1$S(": FTL.TextElement(""),
+ ")": FTL.TextElement(""),
+ ")": FTL.TextElement(""),
+ },
+ ),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("webrtc-item-application"),
+ value=REPLACE(
+ browser,
+ "getUserMedia.sharingMenuApplication",
+ {
+ "%1$S (": FTL.TextElement(""),
+ "%1$S(": FTL.TextElement(""),
+ ")": FTL.TextElement(""),
+ ")": FTL.TextElement(""),
+ },
+ ),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("webrtc-item-screen"),
+ value=REPLACE(
+ browser,
+ "getUserMedia.sharingMenuScreen",
+ {
+ "%1$S (": FTL.TextElement(""),
+ "%1$S(": FTL.TextElement(""),
+ ")": FTL.TextElement(""),
+ ")": FTL.TextElement(""),
+ },
+ ),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("webrtc-item-window"),
+ value=REPLACE(
+ browser,
+ "getUserMedia.sharingMenuWindow",
+ {
+ "%1$S (": FTL.TextElement(""),
+ "%1$S(": FTL.TextElement(""),
+ ")": FTL.TextElement(""),
+ ")": FTL.TextElement(""),
+ },
+ ),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("webrtc-item-browser"),
+ value=REPLACE(
+ browser,
+ "getUserMedia.sharingMenuBrowser",
+ {
+ "%1$S (": FTL.TextElement(""),
+ "%1$S(": FTL.TextElement(""),
+ ")": FTL.TextElement(""),
+ ")": FTL.TextElement(""),
+ },
+ ),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("webrtc-sharing-menuitem-unknown-host"),
+ value=COPY(browser, "getUserMedia.sharingMenuUnknownHost"),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("webrtc-sharing-menuitem"),
+ attributes=[
+ FTL.Attribute(
+ id=FTL.Identifier("label"),
+ value=FTL.Pattern(
+ [FTL.TextElement("{ $origin } ({ $itemList })")]
+ ),
+ ),
+ ],
+ ),
+ FTL.Message(
+ id=FTL.Identifier("webrtc-sharing-menu"),
+ attributes=[
+ FTL.Attribute(
+ id=FTL.Identifier("label"),
+ value=COPY(browser, "getUserMedia.sharingMenu.label"),
+ ),
+ FTL.Attribute(
+ id=FTL.Identifier("accesskey"),
+ value=COPY(browser, "getUserMedia.sharingMenu.accesskey"),
+ ),
+ ],
+ ),
+ FTL.Message(
+ id=FTL.Identifier("webrtc-allow-share-camera"),
+ value=REPLACE(
+ browser,
+ "getUserMedia.shareCamera3.message",
+ {"%1$S": VARIABLE_REFERENCE("origin")},
+ ),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("webrtc-allow-share-microphone"),
+ value=REPLACE(
+ browser,
+ "getUserMedia.shareMicrophone3.message",
+ {"%1$S": VARIABLE_REFERENCE("origin")},
+ ),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("webrtc-allow-share-screen"),
+ value=REPLACE(
+ browser,
+ "getUserMedia.shareScreen4.message",
+ {"%1$S": VARIABLE_REFERENCE("origin")},
+ ),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("webrtc-allow-share-camera-and-microphone"),
+ value=REPLACE(
+ browser,
+ "getUserMedia.shareCameraAndMicrophone3.message",
+ {"%1$S": VARIABLE_REFERENCE("origin")},
+ ),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("webrtc-allow-share-camera-and-audio-capture"),
+ value=REPLACE(
+ browser,
+ "getUserMedia.shareCameraAndAudioCapture3.message",
+ {"%1$S": VARIABLE_REFERENCE("origin")},
+ ),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("webrtc-allow-share-screen-and-microphone"),
+ value=REPLACE(
+ browser,
+ "getUserMedia.shareScreenAndMicrophone4.message",
+ {"%1$S": VARIABLE_REFERENCE("origin")},
+ ),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("webrtc-allow-share-screen-and-audio-capture"),
+ value=REPLACE(
+ browser,
+ "getUserMedia.shareScreenAndAudioCapture4.message",
+ {"%1$S": VARIABLE_REFERENCE("origin")},
+ ),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("webrtc-allow-share-audio-capture"),
+ value=REPLACE(
+ browser,
+ "getUserMedia.shareAudioCapture3.message",
+ {"%1$S": VARIABLE_REFERENCE("origin")},
+ ),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("webrtc-allow-share-speaker"),
+ value=REPLACE(
+ browser,
+ "selectAudioOutput.shareSpeaker.message",
+ {"%1$S": VARIABLE_REFERENCE("origin")},
+ ),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("webrtc-allow-share-camera-unsafe-delegation"),
+ value=REPLACE(
+ browser,
+ "getUserMedia.shareCameraUnsafeDelegation2.message",
+ {
+ "%1$S": VARIABLE_REFERENCE("origin"),
+ "%2$S": VARIABLE_REFERENCE("thirdParty"),
+ },
+ ),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("webrtc-allow-share-microphone-unsafe-delegations"),
+ value=REPLACE(
+ browser,
+ "getUserMedia.shareMicrophoneUnsafeDelegations2.message",
+ {
+ "%1$S": VARIABLE_REFERENCE("origin"),
+ "%2$S": VARIABLE_REFERENCE("thirdParty"),
+ },
+ ),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("webrtc-allow-share-screen-unsafe-delegation"),
+ value=REPLACE(
+ browser,
+ "getUserMedia.shareScreenUnsafeDelegation2.message",
+ {
+ "%1$S": VARIABLE_REFERENCE("origin"),
+ "%2$S": VARIABLE_REFERENCE("thirdParty"),
+ },
+ ),
+ ),
+ FTL.Message(
+ id=FTL.Identifier(
+ "webrtc-allow-share-camera-and-microphone-unsafe-delegation"
+ ),
+ value=REPLACE(
+ browser,
+ "getUserMedia.shareCameraAndMicrophoneUnsafeDelegation2.message",
+ {
+ "%1$S": VARIABLE_REFERENCE("origin"),
+ "%2$S": VARIABLE_REFERENCE("thirdParty"),
+ },
+ ),
+ ),
+ FTL.Message(
+ id=FTL.Identifier(
+ "webrtc-allow-share-camera-and-audio-capture-unsafe-delegation"
+ ),
+ value=REPLACE(
+ browser,
+ "getUserMedia.shareCameraAndAudioCaptureUnsafeDelegation2.message",
+ {
+ "%1$S": VARIABLE_REFERENCE("origin"),
+ "%2$S": VARIABLE_REFERENCE("thirdParty"),
+ },
+ ),
+ ),
+ FTL.Message(
+ id=FTL.Identifier(
+ "webrtc-allow-share-screen-and-microphone-unsafe-delegation"
+ ),
+ value=REPLACE(
+ browser,
+ "getUserMedia.shareScreenAndMicrophoneUnsafeDelegation2.message",
+ {
+ "%1$S": VARIABLE_REFERENCE("origin"),
+ "%2$S": VARIABLE_REFERENCE("thirdParty"),
+ },
+ ),
+ ),
+ FTL.Message(
+ id=FTL.Identifier(
+ "webrtc-allow-share-screen-and-audio-capture-unsafe-delegation"
+ ),
+ value=REPLACE(
+ browser,
+ "getUserMedia.shareScreenAndAudioCaptureUnsafeDelegation2.message",
+ {
+ "%1$S": VARIABLE_REFERENCE("origin"),
+ "%2$S": VARIABLE_REFERENCE("thirdParty"),
+ },
+ ),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("webrtc-allow-share-speaker-unsafe-delegation"),
+ value=REPLACE(
+ browser,
+ "selectAudioOutput.shareSpeakerUnsafeDelegation.message",
+ {
+ "%1$S": VARIABLE_REFERENCE("origin"),
+ "%2$S": VARIABLE_REFERENCE("thirdParty"),
+ },
+ ),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("webrtc-share-screen-warning"),
+ value=COPY(browser, "getUserMedia.shareScreenWarning2.message"),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("webrtc-share-browser-warning"),
+ value=REPLACE(
+ browser,
+ "getUserMedia.shareFirefoxWarning2.message",
+ {"%1$S": TERM_REFERENCE("brand-short-name")},
+ ),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("webrtc-share-screen-learn-more"),
+ value=COPY(browser, "getUserMedia.shareScreen.learnMoreLabel"),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("webrtc-pick-window-or-screen"),
+ value=COPY(browser, "getUserMedia.pickWindowOrScreen.label"),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("webrtc-share-entire-screen"),
+ value=COPY(browser, "getUserMedia.shareEntireScreen.label"),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("webrtc-share-pipe-wire-portal"),
+ value=COPY(browser, "getUserMedia.sharePipeWirePortal.label"),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("webrtc-share-monitor"),
+ value=REPLACE(
+ browser,
+ "getUserMedia.shareMonitor.label",
+ {"%1$S": VARIABLE_REFERENCE("monitorIndex")},
+ ),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("webrtc-share-application"),
+ value=PLURALS(
+ browser,
+ "getUserMedia.shareApplicationWindowCount.label",
+ VARIABLE_REFERENCE("windowCount"),
+ foreach=lambda n: REPLACE_IN_TEXT(
+ n,
+ {
+ "#1": VARIABLE_REFERENCE("appName"),
+ "#2": VARIABLE_REFERENCE("windowCount"),
+ },
+ ),
+ ),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("webrtc-action-allow"),
+ attributes=[
+ FTL.Attribute(
+ id=FTL.Identifier("label"),
+ value=COPY(browser, "getUserMedia.allow.label"),
+ ),
+ FTL.Attribute(
+ id=FTL.Identifier("accesskey"),
+ value=COPY(browser, "getUserMedia.allow.accesskey"),
+ ),
+ ],
+ ),
+ FTL.Message(
+ id=FTL.Identifier("webrtc-action-block"),
+ attributes=[
+ FTL.Attribute(
+ id=FTL.Identifier("label"),
+ value=COPY_PATTERN(
+ browser_ftl, "popup-screen-sharing-block.label"
+ ),
+ ),
+ FTL.Attribute(
+ id=FTL.Identifier("accesskey"),
+ value=COPY_PATTERN(
+ browser_ftl, "popup-screen-sharing-block.accesskey"
+ ),
+ ),
+ ],
+ ),
+ FTL.Message(
+ id=FTL.Identifier("webrtc-action-always-block"),
+ attributes=[
+ FTL.Attribute(
+ id=FTL.Identifier("label"),
+ value=COPY_PATTERN(
+ browser_ftl, "popup-screen-sharing-always-block.label"
+ ),
+ ),
+ FTL.Attribute(
+ id=FTL.Identifier("accesskey"),
+ value=COPY_PATTERN(
+ browser_ftl,
+ "popup-screen-sharing-always-block.accesskey",
+ ),
+ ),
+ ],
+ ),
+ FTL.Message(
+ id=FTL.Identifier("webrtc-action-not-now"),
+ attributes=[
+ FTL.Attribute(
+ id=FTL.Identifier("label"),
+ value=COPY(browser, "getUserMedia.notNow.label"),
+ ),
+ FTL.Attribute(
+ id=FTL.Identifier("accesskey"),
+ value=COPY(browser, "getUserMedia.notNow.accesskey"),
+ ),
+ ],
+ ),
+ FTL.Message(
+ id=FTL.Identifier("webrtc-remember-allow-checkbox"),
+ value=COPY(browser, "getUserMedia.remember"),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("webrtc-mute-notifications-checkbox"),
+ value=COPY_PATTERN(browser_ftl, "popup-mute-notifications-checkbox"),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("webrtc-reason-for-no-permanent-allow-screen"),
+ value=REPLACE(
+ browser,
+ "getUserMedia.reasonForNoPermanentAllow.screen3",
+ {"%1$S": TERM_REFERENCE("brand-short-name")},
+ ),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("webrtc-reason-for-no-permanent-allow-audio"),
+ value=REPLACE(
+ browser,
+ "getUserMedia.reasonForNoPermanentAllow.audio",
+ {"%1$S": TERM_REFERENCE("brand-short-name")},
+ ),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("webrtc-reason-for-no-permanent-allow-insecure"),
+ value=REPLACE(
+ browser,
+ "getUserMedia.reasonForNoPermanentAllow.insecure",
+ {"%1$S": TERM_REFERENCE("brand-short-name")},
+ ),
+ ),
+ ],
+ )
+
+ ctx.add_transforms(
+ browser_ftl,
+ browser_ftl,
+ [
+ FTL.Message(
+ id=FTL.Identifier("popup-select-window-or-screen"),
+ attributes=[
+ FTL.Attribute(
+ id=FTL.Identifier("label"),
+ value=COPY(browser, "getUserMedia.selectWindowOrScreen2.label"),
+ ),
+ FTL.Attribute(
+ id=FTL.Identifier("accesskey"),
+ value=COPY(
+ browser, "getUserMedia.selectWindowOrScreen2.accesskey"
+ ),
+ ),
+ ],
+ ),
+ ],
+ )
diff --git a/python/l10n/fluent_migrations/bug_1813077_popup_notification_learn_more.py b/python/l10n/fluent_migrations/bug_1813077_popup_notification_learn_more.py
new file mode 100644
index 0000000000..bba68d163e
--- /dev/null
+++ b/python/l10n/fluent_migrations/bug_1813077_popup_notification_learn_more.py
@@ -0,0 +1,22 @@
+# coding=utf8
+
+# Any copyright is dedicated to the Public Domain.
+# http://creativecommons.org/publicdomain/zero/1.0/
+
+from __future__ import absolute_import
+import fluent.syntax.ast as FTL
+from fluent.migrate.helpers import transforms_from
+
+
+def migrate(ctx):
+ """Bug 1813077 - Migrate xpinstallPromptMessage.learnMore to Fluent , part {index}."""
+
+ ctx.add_transforms(
+ "browser/browser/browser.ftl",
+ "browser/browser/browser.ftl",
+ transforms_from(
+ """
+popup-notification-xpinstall-prompt-learn-more = { COPY("browser/chrome/browser/browser.properties", "xpinstallPromptMessage.learnMore") }
+"""
+ ),
+ )
diff --git a/python/l10n/fluent_migrations/bug_1814261_mixed_content_identity_panel.py b/python/l10n/fluent_migrations/bug_1814261_mixed_content_identity_panel.py
new file mode 100644
index 0000000000..a135870df8
--- /dev/null
+++ b/python/l10n/fluent_migrations/bug_1814261_mixed_content_identity_panel.py
@@ -0,0 +1,49 @@
+# Any copyright is dedicated to the Public Domain.
+# http://creativecommons.org/publicdomain/zero/1.0/
+
+import fluent.syntax.ast as FTL
+
+from fluent.migrate.transforms import TransformPattern
+
+
+class STRIP_LEARNMORE(TransformPattern):
+ # Used to remove `<a data-l10n-name="link">SOME TEXT</a>` from a string
+ def visit_TextElement(self, node):
+ link_start = node.value.find('<label data-l10n-name="link">')
+ if link_start != -1:
+ # Replace string up to the link, remove remaining spaces afterwards.
+ # Removing an extra character directly is not safe, as it could be
+ # punctuation.
+ node.value = node.value[:link_start].rstrip()
+
+ return node
+
+
+def migrate(ctx):
+ """Bug 1814261 - Use moz-support-link in the mixed-content section of the identity panel, part {index}."""
+
+ browser_ftl = "browser/browser/browser.ftl"
+ ctx.add_transforms(
+ browser_ftl,
+ browser_ftl,
+ [
+ FTL.Message(
+ id=FTL.Identifier("identity-description-active-blocked2"),
+ value=STRIP_LEARNMORE(
+ browser_ftl, "identity-description-active-blocked"
+ ),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("identity-description-passive-loaded-insecure2"),
+ value=STRIP_LEARNMORE(
+ browser_ftl, "identity-description-passive-loaded-insecure"
+ ),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("identity-description-passive-loaded-mixed2"),
+ value=STRIP_LEARNMORE(
+ browser_ftl, "identity-description-passive-loaded-mixed"
+ ),
+ ),
+ ],
+ )
diff --git a/python/l10n/fluent_migrations/bug_1814266_identity_custom_root.py b/python/l10n/fluent_migrations/bug_1814266_identity_custom_root.py
new file mode 100644
index 0000000000..7eb144230d
--- /dev/null
+++ b/python/l10n/fluent_migrations/bug_1814266_identity_custom_root.py
@@ -0,0 +1,34 @@
+# Any copyright is dedicated to the Public Domain.
+# http://creativecommons.org/publicdomain/zero/1.0/
+
+import fluent.syntax.ast as FTL
+
+from fluent.migrate.transforms import TransformPattern
+
+
+class STRIP_LEARNMORE(TransformPattern):
+ # Used to remove `<a data-l10n-name="link">SOME TEXT</a>` from a string
+ def visit_TextElement(self, node):
+ link_start = node.value.find('<label data-l10n-name="link">')
+ # Replace string up to the link, remove remaining spaces afterwards.
+ # Removing an extra character directly is not safe, as it could be
+ # punctuation.
+ node.value = node.value[:link_start].rstrip()
+
+ return node
+
+
+def migrate(ctx):
+ """Bug 1814266 - Use moz-support-link in identity panel, part {index}."""
+
+ browser_ftl = "browser/browser/browser.ftl"
+ ctx.add_transforms(
+ browser_ftl,
+ browser_ftl,
+ [
+ FTL.Message(
+ id=FTL.Identifier("identity-description-custom-root2"),
+ value=STRIP_LEARNMORE(browser_ftl, "identity-description-custom-root"),
+ ),
+ ],
+ )
diff --git a/python/l10n/fluent_migrations/bug_1818322_mozTabList.py b/python/l10n/fluent_migrations/bug_1818322_mozTabList.py
new file mode 100644
index 0000000000..9be3037550
--- /dev/null
+++ b/python/l10n/fluent_migrations/bug_1818322_mozTabList.py
@@ -0,0 +1,26 @@
+# 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 1818322 - Create MozTabList and MozTabRow reusable components, part {index}."""
+ ctx.add_transforms(
+ "toolkit/toolkit/global/mozTabList.ftl",
+ "toolkit/toolkit/global/mozTabList.ftl",
+ transforms_from(
+ """
+mztabrow-tabs-list-tab =
+ .title = {COPY_PATTERN(from_path, "firefoxview-tabs-list-tab-button.title")}
+mztabrow-dismiss-tab-button =
+ .title = {COPY_PATTERN(from_path, "firefoxview-closed-tabs-dismiss-tab.title")}
+mztabrow-just-now-timestamp = {COPY_PATTERN(from_path, "firefoxview-just-now-timestamp")}
+ """,
+ from_path="browser/browser/firefoxView.ftl",
+ ),
+ )
diff --git a/python/l10n/fluent_migrations/bug_1820654_update_manual.py b/python/l10n/fluent_migrations/bug_1820654_update_manual.py
new file mode 100644
index 0000000000..fe3a18e38b
--- /dev/null
+++ b/python/l10n/fluent_migrations/bug_1820654_update_manual.py
@@ -0,0 +1,30 @@
+# Any copyright is dedicated to the Public Domain.
+# http://creativecommons.org/publicdomain/zero/1.0/
+
+import fluent.syntax.ast as FTL
+
+from fluent.migrate.transforms import TransformPattern
+
+
+class REPLACE_LABEL(TransformPattern):
+ # Used to replace `<label data-l10n-name="manual-link"/>`
+ def visit_TextElement(self, node):
+ node.value = node.value.replace("<label", "<a")
+
+ return node
+
+
+def migrate(ctx):
+ """Bug 1820654 - Use html:a in manualUpdate box, part {index}."""
+
+ aboutDialog_ftl = "browser/browser/aboutDialog.ftl"
+ ctx.add_transforms(
+ aboutDialog_ftl,
+ aboutDialog_ftl,
+ [
+ FTL.Message(
+ id=FTL.Identifier("aboutdialog-update-manual"),
+ value=REPLACE_LABEL(aboutDialog_ftl, "update-manual"),
+ ),
+ ],
+ )
diff --git a/python/l10n/fluent_migrations/bug_1821187_migrationWizard_password_file_import_strings.py b/python/l10n/fluent_migrations/bug_1821187_migrationWizard_password_file_import_strings.py
new file mode 100644
index 0000000000..9f74ff9837
--- /dev/null
+++ b/python/l10n/fluent_migrations/bug_1821187_migrationWizard_password_file_import_strings.py
@@ -0,0 +1,27 @@
+# coding=utf8
+
+# Any copyright is dedicated to the Public Domain.
+# http://creativecommons.org/publicdomain/zero/1.0/
+
+from __future__ import absolute_import
+import fluent.syntax.ast as FTL
+from fluent.migrate import COPY_PATTERN
+from fluent.migrate.helpers import transforms_from
+
+
+def migrate(ctx):
+ """Bug 1821187 - Copy password file import strings to migrationWizard.ftl, part {index}."""
+
+ ctx.add_transforms(
+ "browser/browser/migrationWizard.ftl",
+ "browser/browser/migrationWizard.ftl",
+ transforms_from(
+ """
+migration-passwords-from-file-csv-filter-title =
+ {COPY_PATTERN(from_path, "about-logins-import-file-picker-csv-filter-title")}
+migration-passwords-from-file-tsv-filter-title =
+ {COPY_PATTERN(from_path, "about-logins-import-file-picker-tsv-filter-title")}
+ """,
+ from_path="browser/browser/aboutLogins.ftl",
+ ),
+ )
diff --git a/python/l10n/fluent_migrations/bug_1821779_migrationWizard_browser_names.py b/python/l10n/fluent_migrations/bug_1821779_migrationWizard_browser_names.py
new file mode 100644
index 0000000000..6bcaa35da8
--- /dev/null
+++ b/python/l10n/fluent_migrations/bug_1821779_migrationWizard_browser_names.py
@@ -0,0 +1,38 @@
+# coding=utf8
+
+# Any copyright is dedicated to the Public Domain.
+# http://creativecommons.org/publicdomain/zero/1.0/
+
+from __future__ import absolute_import
+import fluent.syntax.ast as FTL
+from fluent.migrate.helpers import transforms_from
+
+
+def migrate(ctx):
+ """Bug 1821779 - Move existing browser names to migrationWizard.ftl, part {index}."""
+
+ ctx.add_transforms(
+ "browser/browser/migrationWizard.ftl",
+ "browser/browser/migrationWizard.ftl",
+ transforms_from(
+ """
+migration-wizard-migrator-display-name-brave = {COPY_PATTERN(from_path, "import-from-brave.label")}
+migration-wizard-migrator-display-name-canary = {COPY_PATTERN(from_path, "import-from-canary.label")}
+migration-wizard-migrator-display-name-chrome = {COPY_PATTERN(from_path, "import-from-chrome.label")}
+migration-wizard-migrator-display-name-chrome-beta = {COPY_PATTERN(from_path, "import-from-chrome-beta.label")}
+migration-wizard-migrator-display-name-chrome-dev = {COPY_PATTERN(from_path, "import-from-chrome-dev.label")}
+migration-wizard-migrator-display-name-chromium = {COPY_PATTERN(from_path, "import-from-chromium.label")}
+migration-wizard-migrator-display-name-chromium-360se = {COPY_PATTERN(from_path, "import-from-360se.label")}
+migration-wizard-migrator-display-name-chromium-edge = {COPY_PATTERN(from_path, "import-from-edge.label")}
+migration-wizard-migrator-display-name-chromium-edge-beta = {COPY_PATTERN(from_path, "import-from-edge-beta.label")}
+migration-wizard-migrator-display-name-edge-legacy = {COPY_PATTERN(from_path, "import-from-edge-legacy.label")}
+migration-wizard-migrator-display-name-firefox = {COPY_PATTERN(from_path, "import-from-firefox.label")}
+migration-wizard-migrator-display-name-ie = {COPY_PATTERN(from_path, "import-from-ie.label")}
+migration-wizard-migrator-display-name-opera = {COPY_PATTERN(from_path, "import-from-opera.label")}
+migration-wizard-migrator-display-name-opera-gx = {COPY_PATTERN(from_path, "import-from-opera-gx.label")}
+migration-wizard-migrator-display-name-safari = {COPY_PATTERN(from_path, "import-from-safari.label")}
+migration-wizard-migrator-display-name-vivaldi = {COPY_PATTERN(from_path, "import-from-vivaldi.label")}
+""",
+ from_path="browser/browser/migration.ftl",
+ ),
+ )
diff --git a/python/l10n/fluent_migrations/bug_1828443_pocket_policy.py b/python/l10n/fluent_migrations/bug_1828443_pocket_policy.py
new file mode 100644
index 0000000000..6f9fbe5d7b
--- /dev/null
+++ b/python/l10n/fluent_migrations/bug_1828443_pocket_policy.py
@@ -0,0 +1,30 @@
+# Any copyright is dedicated to the Public Domain.
+# http://creativecommons.org/publicdomain/zero/1.0/
+
+import fluent.syntax.ast as FTL
+
+from fluent.migrate.transforms import TransformPattern
+
+
+class REPLACE_POCKET(TransformPattern):
+ # Replace Pocket with term `{ -pocket-brand-name }`
+ def visit_TextElement(self, node):
+ node.value = node.value.replace("Pocket", "{ -pocket-brand-name }")
+
+ return node
+
+
+def migrate(ctx):
+ """Bug 1828443 - Use Fluent term for Pocket in policy string, part {index}."""
+
+ ftl_file = "browser/browser/policies/policies-descriptions.ftl"
+ ctx.add_transforms(
+ ftl_file,
+ ftl_file,
+ [
+ FTL.Message(
+ id=FTL.Identifier("policy-DisablePocket2"),
+ value=REPLACE_POCKET(ftl_file, "policy-DisablePocket"),
+ ),
+ ],
+ )
diff --git a/python/l10n/fluent_migrations/bug_1828767_sanitize_dialog_native_size.py b/python/l10n/fluent_migrations/bug_1828767_sanitize_dialog_native_size.py
new file mode 100644
index 0000000000..9d311c3fae
--- /dev/null
+++ b/python/l10n/fluent_migrations/bug_1828767_sanitize_dialog_native_size.py
@@ -0,0 +1,77 @@
+from fluent.migrate import COPY_PATTERN
+from fluent.migrate.transforms import TransformPattern, REPLACE_IN_TEXT
+from fluent.migrate.helpers import MESSAGE_REFERENCE
+import fluent.syntax.ast as FTL
+
+# Any copyright is dedicated to the Public Domain.
+# http://creativecommons.org/publicdomain/zero/1.0/
+
+
+class REPLACE_PATTERN(TransformPattern):
+ """Hacky custom transform that works."""
+
+ def __init__(self, ctx, path, key, replacements, **kwargs):
+ super(REPLACE_PATTERN, self).__init__(path, key, **kwargs)
+ self.ctx = ctx
+ self.replacements = replacements
+
+ def visit_Pattern(self, source):
+ source = self.generic_visit(source)
+ target = FTL.Pattern([])
+ for element in source.elements:
+ if isinstance(element, FTL.TextElement):
+ pattern = REPLACE_IN_TEXT(element, self.replacements)(self.ctx)
+ target.elements += pattern.elements
+ else:
+ target.elements += [element]
+ return target
+
+
+def replace_with_min_size_transform(ctx, file, identifier, to_identifier=None):
+ if to_identifier is None:
+ to_identifier = identifier + "2"
+ attributes = [
+ FTL.Attribute(
+ id=FTL.Identifier("title"),
+ value=COPY_PATTERN(file, "{}.title".format(identifier)),
+ ),
+ FTL.Attribute(
+ id=FTL.Identifier("style"),
+ value=REPLACE_PATTERN(
+ ctx,
+ file,
+ "{}.style".format(identifier),
+ {
+ "width:": FTL.TextElement("min-width:"),
+ "height:": FTL.TextElement("min-height:"),
+ },
+ ),
+ ),
+ ]
+
+ return FTL.Message(
+ id=FTL.Identifier(to_identifier),
+ attributes=attributes,
+ )
+
+
+def migrate(ctx):
+ """Bug 1828767 - Migrate sanitize dialog to use min-width, part {index}."""
+ ctx.add_transforms(
+ "browser/browser/sanitize.ftl",
+ "browser/browser/sanitize.ftl",
+ [
+ replace_with_min_size_transform(
+ ctx,
+ "browser/browser/sanitize.ftl",
+ "dialog-title",
+ "sanitize-dialog-title",
+ ),
+ replace_with_min_size_transform(
+ ctx,
+ "browser/browser/sanitize.ftl",
+ "dialog-title-everything",
+ "sanitize-dialog-title-everything",
+ ),
+ ],
+ )
diff --git a/python/l10n/fluent_migrations/bug_1830042_places.py b/python/l10n/fluent_migrations/bug_1830042_places.py
new file mode 100644
index 0000000000..0109d3952f
--- /dev/null
+++ b/python/l10n/fluent_migrations/bug_1830042_places.py
@@ -0,0 +1,127 @@
+# 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 TERM_REFERENCE, transforms_from, VARIABLE_REFERENCE
+from fluent.migrate.transforms import COPY, PLURALS, REPLACE, REPLACE_IN_TEXT
+
+
+def migrate(ctx):
+ """Bug 1830042 - Convert places.properties to Fluent, part {index}."""
+
+ source = "browser/chrome/browser/places/places.properties"
+ target = "browser/browser/places.ftl"
+ ctx.add_transforms(
+ target,
+ target,
+ [
+ FTL.Message(
+ id=FTL.Identifier("places-details-pane-no-items"),
+ attributes=[
+ FTL.Attribute(
+ id=FTL.Identifier("value"),
+ value=COPY(source, "detailsPane.noItems"),
+ )
+ ],
+ ),
+ FTL.Message(
+ id=FTL.Identifier("places-details-pane-items-count"),
+ attributes=[
+ FTL.Attribute(
+ id=FTL.Identifier("value"),
+ value=PLURALS(
+ source,
+ "detailsPane.itemsCountLabel",
+ VARIABLE_REFERENCE("count"),
+ foreach=lambda n: REPLACE_IN_TEXT(
+ n,
+ {"#1": VARIABLE_REFERENCE("count")},
+ ),
+ ),
+ )
+ ],
+ ),
+ FTL.Message(
+ id=FTL.Identifier("places-locked-prompt"),
+ value=REPLACE(
+ source,
+ "lockPrompt.text",
+ {"%1$S": TERM_REFERENCE("brand-short-name")},
+ ),
+ ),
+ ]
+ + transforms_from(
+ """
+places-empty-bookmarks-folder =
+ .label = { COPY(source, "bookmarksMenuEmptyFolder") }
+places-delete-page =
+ .label =
+ { $count ->
+ [1] { COPY(source, "cmd.deleteSinglePage.label") }
+ *[other] { COPY(source, "cmd.deleteMultiplePages.label") }
+ }
+ .accesskey = { COPY(source, "cmd.deleteSinglePage.accesskey") }
+places-create-bookmark =
+ .label =
+ { $count ->
+ [1] { COPY(source, "cmd.bookmarkSinglePage2.label") }
+ *[other] { COPY(source, "cmd.bookmarkMultiplePages2.label") }
+ }
+ .accesskey = { COPY(source, "cmd.bookmarkSinglePage2.accesskey") }
+places-search-bookmarks =
+ .placeholder = { COPY(source, "searchBookmarks") }
+places-search-history =
+ .placeholder = { COPY(source, "searchHistory") }
+places-search-downloads =
+ .placeholder = { COPY(source, "searchDownloads") }
+places-view-sortby-name =
+ .label = { COPY(source, "view.sortBy.1.name.label") }
+ .accesskey = { COPY(source, "view.sortBy.1.name.accesskey") }
+places-view-sortby-url =
+ .label = { COPY(source, "view.sortBy.1.url.label") }
+ .accesskey = { COPY(source, "view.sortBy.1.url.accesskey") }
+places-view-sortby-date =
+ .label = { COPY(source, "view.sortBy.1.date.label") }
+ .accesskey = { COPY(source, "view.sortBy.1.date.accesskey") }
+places-view-sortby-visit-count =
+ .label = { COPY(source, "view.sortBy.1.visitCount.label") }
+ .accesskey = { COPY(source, "view.sortBy.1.visitCount.accesskey") }
+places-view-sortby-date-added =
+ .label = { COPY(source, "view.sortBy.1.dateAdded.label") }
+ .accesskey = { COPY(source, "view.sortBy.1.dateAdded.accesskey") }
+places-view-sortby-last-modified =
+ .label = { COPY(source, "view.sortBy.1.lastModified.label") }
+ .accesskey = { COPY(source, "view.sortBy.1.lastModified.accesskey") }
+places-view-sortby-tags =
+ .label = { COPY(source, "view.sortBy.1.tags.label") }
+ .accesskey = { COPY(source, "view.sortBy.1.tags.accesskey") }
+""",
+ source=source,
+ ),
+ )
+
+ ctx.add_transforms(
+ "browser/browser/placesPrompts.ftl",
+ "browser/browser/placesPrompts.ftl",
+ [
+ FTL.Message(
+ id=FTL.Identifier("places-error-title"),
+ value=FTL.Pattern([FTL.Placeable(TERM_REFERENCE("brand-short-name"))]),
+ ),
+ ]
+ + transforms_from(
+ """
+places-no-title = { COPY(source, "noTitle") }
+places-bookmarks-backup-title = { COPY(source, "bookmarksBackupTitle") }
+places-bookmarks-restore-alert-title = { COPY(source, "bookmarksRestoreAlertTitle") }
+places-bookmarks-restore-alert = { COPY(source, "bookmarksRestoreAlert") }
+places-bookmarks-restore-title = { COPY(source, "bookmarksRestoreTitle") }
+places-bookmarks-restore-filter-name = { COPY(source, "bookmarksRestoreFilterName") }
+places-bookmarks-restore-format-error = { COPY(source, "bookmarksRestoreFormatError") }
+places-bookmarks-restore-parse-error = { COPY(source, "bookmarksRestoreParseError") }
+places-bookmarks-import = { COPY(source, "SelectImport") }
+places-bookmarks-export = { COPY(source, "EnterExport") }
+""",
+ source=source,
+ ),
+ )
diff --git a/python/l10n/fluent_migrations/bug_1831851_accounts.py b/python/l10n/fluent_migrations/bug_1831851_accounts.py
new file mode 100644
index 0000000000..d50a0192c8
--- /dev/null
+++ b/python/l10n/fluent_migrations/bug_1831851_accounts.py
@@ -0,0 +1,195 @@
+# 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
+from fluent.migrate.transforms import COPY, PLURALS, REPLACE, REPLACE_IN_TEXT
+
+
+def migrate(ctx):
+ """Bug 1831851 - Migrate accounts.properties to Fluent, part {index}."""
+
+ accounts = "browser/chrome/browser/accounts.properties"
+ accounts_ftl = "browser/browser/accounts.ftl"
+ preferences_ftl = "browser/browser/preferences/preferences.ftl"
+
+ ctx.add_transforms(
+ accounts_ftl,
+ accounts_ftl,
+ [
+ FTL.Message(
+ id=FTL.Identifier("account-reconnect"),
+ value=REPLACE(
+ accounts,
+ "reconnectDescription",
+ {"%1$S": VARIABLE_REFERENCE("email")},
+ ),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("account-verify"),
+ value=REPLACE(
+ accounts, "verifyDescription", {"%1$S": VARIABLE_REFERENCE("email")}
+ ),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("account-send-to-all-devices-titlecase"),
+ value=COPY(accounts, "sendToAllDevices.menuitem"),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("account-manage-devices-titlecase"),
+ value=COPY(accounts, "manageDevices.menuitem"),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("account-send-tab-to-device-singledevice-status"),
+ value=COPY(accounts, "sendTabToDevice.singledevice.status"),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("account-send-tab-to-device-singledevice-learnmore"),
+ value=COPY(accounts, "sendTabToDevice.singledevice"),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("account-send-tab-to-device-connectdevice"),
+ value=COPY(accounts, "sendTabToDevice.connectdevice"),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("account-send-tab-to-device-verify-status"),
+ value=COPY(accounts, "sendTabToDevice.verify.status"),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("account-send-tab-to-device-verify"),
+ value=COPY(accounts, "sendTabToDevice.verify"),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("account-connection-title"),
+ value=FTL.Pattern(
+ [
+ FTL.Placeable(
+ FTL.TermReference(
+ id=FTL.Identifier("fxaccount-brand-name"),
+ arguments=FTL.CallArguments(
+ named=[
+ FTL.NamedArgument(
+ FTL.Identifier("capitalization"),
+ FTL.StringLiteral("title"),
+ )
+ ]
+ ),
+ )
+ )
+ ]
+ ),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("account-connection-connected-with"),
+ value=REPLACE(
+ accounts,
+ "otherDeviceConnectedBody",
+ {"%1$S": VARIABLE_REFERENCE("deviceName")},
+ ),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("account-connection-connected-with-noname"),
+ value=COPY(accounts, "otherDeviceConnectedBody.noDeviceName"),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("account-connection-connected"),
+ value=COPY(accounts, "thisDeviceConnectedBody"),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("account-connection-disconnected"),
+ value=COPY(accounts, "thisDeviceDisconnectedBody"),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("account-single-tab-arriving-title"),
+ value=COPY(accounts, "tabArrivingNotification.title"),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("account-single-tab-arriving-from-device-title"),
+ value=REPLACE(
+ accounts,
+ "tabArrivingNotificationWithDevice.title",
+ {"%1$S": VARIABLE_REFERENCE("deviceName")},
+ ),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("account-single-tab-arriving-truncated-url"),
+ value=REPLACE(
+ accounts,
+ "singleTabArrivingWithTruncatedURL.body",
+ {"%1$S": VARIABLE_REFERENCE("url")},
+ ),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("account-multiple-tabs-arriving-title"),
+ value=COPY(accounts, "multipleTabsArrivingNotification.title"),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("account-multiple-tabs-arriving-from-single-device"),
+ value=PLURALS(
+ accounts,
+ "unnamedTabsArrivingNotification2.body",
+ VARIABLE_REFERENCE("tabCount"),
+ foreach=lambda n: REPLACE_IN_TEXT(
+ n,
+ {
+ "#1": VARIABLE_REFERENCE("tabCount"),
+ "#2": VARIABLE_REFERENCE("deviceName"),
+ },
+ ),
+ ),
+ ),
+ FTL.Message(
+ id=FTL.Identifier(
+ "account-multiple-tabs-arriving-from-multiple-devices"
+ ),
+ value=PLURALS(
+ accounts,
+ "unnamedTabsArrivingNotificationMultiple2.body",
+ VARIABLE_REFERENCE("tabCount"),
+ foreach=lambda n: REPLACE_IN_TEXT(
+ n,
+ {"#1": VARIABLE_REFERENCE("tabCount")},
+ ),
+ ),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("account-multiple-tabs-arriving-from-unknown-device"),
+ value=PLURALS(
+ accounts,
+ "unnamedTabsArrivingNotificationNoDevice.body",
+ VARIABLE_REFERENCE("tabCount"),
+ foreach=lambda n: REPLACE_IN_TEXT(
+ n,
+ {"#1": VARIABLE_REFERENCE("tabCount")},
+ ),
+ ),
+ ),
+ ],
+ )
+
+ ctx.add_transforms(
+ preferences_ftl,
+ preferences_ftl,
+ [
+ FTL.Message(
+ id=FTL.Identifier("sync-verification-sent-title"),
+ value=COPY(accounts, "verificationSentTitle"),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("sync-verification-sent-body"),
+ value=REPLACE(
+ accounts,
+ "verificationSentBody",
+ {"%1$S": VARIABLE_REFERENCE("email")},
+ ),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("sync-verification-not-sent-title"),
+ value=COPY(accounts, "verificationNotSentTitle"),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("sync-verification-not-sent-body"),
+ value=COPY(accounts, "verificationNotSentBody"),
+ ),
+ ],
+ )
diff --git a/python/l10n/fluent_migrations/bug_1831872_sync.py b/python/l10n/fluent_migrations/bug_1831872_sync.py
new file mode 100644
index 0000000000..f66c27bf5a
--- /dev/null
+++ b/python/l10n/fluent_migrations/bug_1831872_sync.py
@@ -0,0 +1,31 @@
+# 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 TERM_REFERENCE, VARIABLE_REFERENCE
+from fluent.migrate.transforms import REPLACE
+
+
+def migrate(ctx):
+ """Bug 1831872 - Migrate sync.properties to Fluent, part {index}."""
+
+ source = "services/sync/sync.properties"
+ target = "toolkit/services/accounts.ftl"
+ ctx.add_transforms(
+ target,
+ target,
+ [
+ FTL.Message(
+ id=FTL.Identifier("account-client-name"),
+ value=REPLACE(
+ source,
+ "client.name2",
+ {
+ "%1$S": VARIABLE_REFERENCE("user"),
+ "%2$S": TERM_REFERENCE("brand-short-name"),
+ "%3$S": VARIABLE_REFERENCE("system"),
+ },
+ ),
+ ),
+ ],
+ )
diff --git a/python/l10n/fluent_migrations/bug_1832138_ctrlTab.py b/python/l10n/fluent_migrations/bug_1832138_ctrlTab.py
new file mode 100644
index 0000000000..195e3cee49
--- /dev/null
+++ b/python/l10n/fluent_migrations/bug_1832138_ctrlTab.py
@@ -0,0 +1,37 @@
+# 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
+from fluent.migrate.transforms import PLURALS, REPLACE_IN_TEXT
+
+
+def migrate(ctx):
+ """Bug 1832138 - Convert browser-ctrlTab.js to Fluent, part {index}."""
+
+ browser = "browser/chrome/browser/browser.properties"
+ target = "browser/browser/tabbrowser.ftl"
+
+ ctx.add_transforms(
+ target,
+ target,
+ [
+ FTL.Message(
+ id=FTL.Identifier("tabbrowser-ctrl-tab-list-all-tabs"),
+ attributes=[
+ FTL.Attribute(
+ id=FTL.Identifier("label"),
+ value=PLURALS(
+ browser,
+ "ctrlTab.listAllTabs.label",
+ VARIABLE_REFERENCE("tabCount"),
+ foreach=lambda n: REPLACE_IN_TEXT(
+ n,
+ {"#1": VARIABLE_REFERENCE("tabCount")},
+ ),
+ ),
+ )
+ ],
+ ),
+ ],
+ )
diff --git a/python/l10n/fluent_migrations/bug_1832141_recently_closed.py b/python/l10n/fluent_migrations/bug_1832141_recently_closed.py
new file mode 100644
index 0000000000..530f6f05dd
--- /dev/null
+++ b/python/l10n/fluent_migrations/bug_1832141_recently_closed.py
@@ -0,0 +1,76 @@
+import fluent.syntax.ast as FTL
+from fluent.migrate import COPY_PATTERN, PLURALS, REPLACE_IN_TEXT
+from fluent.migrate.helpers import VARIABLE_REFERENCE
+
+# Any copyright is dedicated to the Public Domain.
+# http://creativecommons.org/publicdomain/zero/1.0/
+
+
+class CUSTOM_PLURALS(PLURALS):
+ def __call__(self, ctx):
+ pattern = super().__call__(ctx)
+ el = pattern.elements[0]
+ if isinstance(el, FTL.Placeable) and isinstance(
+ el.expression, FTL.SelectExpression
+ ):
+ selexp = el.expression
+ else:
+ selexp = FTL.SelectExpression(
+ VARIABLE_REFERENCE("tabCount"),
+ [FTL.Variant(FTL.Identifier("other"), pattern, default=True)],
+ )
+ pattern = FTL.Pattern([FTL.Placeable(selexp)])
+ selexp.variants[0:0] = [
+ FTL.Variant(
+ FTL.NumberLiteral("0"),
+ FTL.Pattern([FTL.Placeable(VARIABLE_REFERENCE("winTitle"))]),
+ )
+ ]
+ return pattern
+
+
+def migrate(ctx):
+ """Bug 1832141 - Migrate strings to recentlyClosed.ftl, part {index}."""
+
+ appmenu = "browser/browser/appmenu.ftl"
+ browser = "browser/chrome/browser/browser.properties"
+ menubar = "browser/browser/menubar.ftl"
+ target = "browser/browser/recentlyClosed.ftl"
+
+ ctx.add_transforms(
+ target,
+ target,
+ [
+ FTL.Message(
+ id=FTL.Identifier("recently-closed-menu-reopen-all-tabs"),
+ value=COPY_PATTERN(menubar, "menu-history-reopen-all-tabs"),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("recently-closed-menu-reopen-all-windows"),
+ value=COPY_PATTERN(menubar, "menu-history-reopen-all-windows"),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("recently-closed-panel-reopen-all-tabs"),
+ value=COPY_PATTERN(appmenu, "appmenu-reopen-all-tabs"),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("recently-closed-panel-reopen-all-windows"),
+ value=COPY_PATTERN(appmenu, "appmenu-reopen-all-windows"),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("recently-closed-undo-close-window-label"),
+ value=CUSTOM_PLURALS(
+ browser,
+ "menuUndoCloseWindowLabel",
+ VARIABLE_REFERENCE("tabCount"),
+ foreach=lambda n: REPLACE_IN_TEXT(
+ n,
+ {
+ "#1": VARIABLE_REFERENCE("winTitle"),
+ "#2": VARIABLE_REFERENCE("tabCount"),
+ },
+ ),
+ ),
+ ),
+ ],
+ )
diff --git a/python/l10n/fluent_migrations/bug_1832179_sendTabToDevice.py b/python/l10n/fluent_migrations/bug_1832179_sendTabToDevice.py
new file mode 100644
index 0000000000..526b8a90e0
--- /dev/null
+++ b/python/l10n/fluent_migrations/bug_1832179_sendTabToDevice.py
@@ -0,0 +1,37 @@
+# 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
+from fluent.migrate.transforms import PLURALS, REPLACE_IN_TEXT
+
+
+def migrate(ctx):
+ """Bug 1832179 - Convert sendTabsToDevice.label string to Fluent, part {index}."""
+
+ browser = "browser/chrome/browser/browser.properties"
+ target = "browser/browser/sync.ftl"
+
+ ctx.add_transforms(
+ target,
+ target,
+ [
+ FTL.Message(
+ id=FTL.Identifier("fxa-menu-send-tab-to-device"),
+ attributes=[
+ FTL.Attribute(
+ id=FTL.Identifier("label"),
+ value=PLURALS(
+ browser,
+ "sendTabsToDevice.label",
+ VARIABLE_REFERENCE("tabCount"),
+ foreach=lambda n: REPLACE_IN_TEXT(
+ n,
+ {"#1": VARIABLE_REFERENCE("tabCount")},
+ ),
+ ),
+ )
+ ],
+ ),
+ ],
+ )
diff --git a/python/l10n/fluent_migrations/bug_1832186_popupwarning.py b/python/l10n/fluent_migrations/bug_1832186_popupwarning.py
new file mode 100644
index 0000000000..4239899725
--- /dev/null
+++ b/python/l10n/fluent_migrations/bug_1832186_popupwarning.py
@@ -0,0 +1,139 @@
+# 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 TERM_REFERENCE, VARIABLE_REFERENCE
+from fluent.migrate.transforms import (
+ COPY,
+ PLURALS,
+ REPLACE,
+ REPLACE_IN_TEXT,
+)
+
+
+def migrate(ctx):
+ """Bug 1832186 - Migrate popup warning strings to Fluent, part {index}."""
+
+ source = "browser/chrome/browser/browser.properties"
+ target = "browser/browser/browser.ftl"
+
+ ctx.add_transforms(
+ target,
+ target,
+ [
+ FTL.Message(
+ id=FTL.Identifier("popup-warning-message"),
+ value=PLURALS(
+ source,
+ "popupWarning.message",
+ VARIABLE_REFERENCE("popupCount"),
+ foreach=lambda n: REPLACE_IN_TEXT(
+ n,
+ {
+ "#1": TERM_REFERENCE("brand-short-name"),
+ "#2": VARIABLE_REFERENCE("popupCount"),
+ },
+ ),
+ ),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("popup-warning-exceeded-message"),
+ value=PLURALS(
+ source,
+ "popupWarning.exceeded.message",
+ VARIABLE_REFERENCE("popupCount"),
+ foreach=lambda n: REPLACE_IN_TEXT(
+ n,
+ {
+ "#1": TERM_REFERENCE("brand-short-name"),
+ "#2": VARIABLE_REFERENCE("popupCount"),
+ },
+ ),
+ ),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("popup-warning-button"),
+ attributes=[
+ FTL.Attribute(
+ id=FTL.Identifier("label"),
+ value=FTL.Pattern(
+ [
+ FTL.Placeable(
+ FTL.SelectExpression(
+ selector=FTL.FunctionReference(
+ FTL.Identifier("PLATFORM"),
+ FTL.CallArguments(),
+ ),
+ variants=[
+ FTL.Variant(
+ key=FTL.Identifier("windows"),
+ value=COPY(
+ source, "popupWarningButton"
+ ),
+ ),
+ FTL.Variant(
+ key=FTL.Identifier("other"),
+ value=COPY(
+ source, "popupWarningButtonUnix"
+ ),
+ default=True,
+ ),
+ ],
+ )
+ )
+ ]
+ ),
+ ),
+ FTL.Attribute(
+ id=FTL.Identifier("accesskey"),
+ value=FTL.Pattern(
+ [
+ FTL.Placeable(
+ FTL.SelectExpression(
+ selector=FTL.FunctionReference(
+ FTL.Identifier("PLATFORM"),
+ FTL.CallArguments(),
+ ),
+ variants=[
+ FTL.Variant(
+ key=FTL.Identifier("windows"),
+ value=COPY(
+ source,
+ "popupWarningButton.accesskey",
+ ),
+ ),
+ FTL.Variant(
+ key=FTL.Identifier("other"),
+ value=COPY(
+ source,
+ "popupWarningButtonUnix.accesskey",
+ ),
+ default=True,
+ ),
+ ],
+ )
+ )
+ ]
+ ),
+ ),
+ ],
+ ),
+ FTL.Message(
+ id=FTL.Identifier("popup-show-popup-menuitem"),
+ attributes=[
+ FTL.Attribute(
+ id=FTL.Identifier("label"),
+ value=REPLACE(
+ source,
+ "popupShowPopupPrefix",
+ {
+ "%1$S": VARIABLE_REFERENCE("popupURI"),
+ "‘": FTL.TextElement("“"),
+ "’": FTL.TextElement("”"),
+ },
+ ),
+ )
+ ],
+ ),
+ ],
+ )
diff --git a/python/l10n/fluent_migrations/bug_1832668_firefoxView_navigation.py b/python/l10n/fluent_migrations/bug_1832668_firefoxView_navigation.py
new file mode 100644
index 0000000000..c742f64b36
--- /dev/null
+++ b/python/l10n/fluent_migrations/bug_1832668_firefoxView_navigation.py
@@ -0,0 +1,27 @@
+# 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 1832668 - Add new side navigation component to Firefox View Next page, part {index}."""
+ ctx.add_transforms(
+ "browser/browser/firefoxView.ftl",
+ "browser/browser/firefoxView.ftl",
+ transforms_from(
+ """
+firefoxview-overview-nav = {COPY_PATTERN(from_path, "firefoxview-overview-navigation")}
+ .title = {COPY_PATTERN(from_path, "firefoxview-overview-navigation")}
+firefoxview-history-nav = {COPY_PATTERN(from_path, "firefoxview-history-navigation")}
+ .title = {COPY_PATTERN(from_path, "firefoxview-history-navigation")}
+firefoxview-opentabs-nav = {COPY_PATTERN(from_path, "firefoxview-opentabs-navigation")}
+ .title = {COPY_PATTERN(from_path, "firefoxview-opentabs-navigation")}
+ """,
+ from_path="browser/browser/firefoxView.ftl",
+ ),
+ )
diff --git a/python/l10n/fluent_migrations/bug_1833228_fxviewTabList.py b/python/l10n/fluent_migrations/bug_1833228_fxviewTabList.py
new file mode 100644
index 0000000000..43d0d8834c
--- /dev/null
+++ b/python/l10n/fluent_migrations/bug_1833228_fxviewTabList.py
@@ -0,0 +1,44 @@
+# 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 1833228 - Remove "moz-" from moz-tab-list component and associated .ftl, .css files, part {index}."""
+ ctx.add_transforms(
+ "browser/browser/fxviewTabList.ftl",
+ "browser/browser/fxviewTabList.ftl",
+ transforms_from(
+ """
+fxviewtabrow-open-menu-button =
+ .title = {COPY_PATTERN(from_path, "mztabrow-open-menu-button.title")}
+fxviewtabrow-date = {COPY_PATTERN(from_path, "mztabrow-date")}
+fxviewtabrow-time = {COPY_PATTERN(from_path, "mztabrow-time")}
+fxviewtabrow-tabs-list-tab =
+ .title = {COPY_PATTERN(from_path, "mztabrow-tabs-list-tab.title")}
+fxviewtabrow-dismiss-tab-button =
+ .title = {COPY_PATTERN(from_path, "mztabrow-dismiss-tab-button.title")}
+fxviewtabrow-just-now-timestamp = {COPY_PATTERN(from_path, "mztabrow-just-now-timestamp")}
+fxviewtabrow-delete = {COPY_PATTERN(from_path, "mztabrow-delete")}
+ .accesskey = {COPY_PATTERN(from_path, "mztabrow-delete.accesskey")}
+fxviewtabrow-forget-about-this-site = {COPY_PATTERN(from_path, "mztabrow-forget-about-this-site")}
+ .accesskey = {COPY_PATTERN(from_path, "mztabrow-forget-about-this-site.accesskey")}
+fxviewtabrow-open-in-window = {COPY_PATTERN(from_path, "mztabrow-open-in-window")}
+ .accesskey = {COPY_PATTERN(from_path, "mztabrow-open-in-window.accesskey")}
+fxviewtabrow-open-in-private-window = {COPY_PATTERN(from_path, "mztabrow-open-in-private-window")}
+ .accesskey = {COPY_PATTERN(from_path, "mztabrow-open-in-private-window.accesskey")}
+fxviewtabrow-add-bookmark = {COPY_PATTERN(from_path, "mztabrow-add-bookmark")}
+ .accesskey = {COPY_PATTERN(from_path, "mztabrow-add-bookmark.accesskey")}
+fxviewtabrow-save-to-pocket = {COPY_PATTERN(from_path, "mztabrow-save-to-pocket")}
+ .accesskey = {COPY_PATTERN(from_path, "mztabrow-save-to-pocket.accesskey")}
+fxviewtabrow-copy-link = {COPY_PATTERN(from_path, "mztabrow-copy-link")}
+ .accesskey = {COPY_PATTERN(from_path, "mztabrow-copy-link.accesskey")}
+ """,
+ from_path="browser/browser/mozTabList.ftl",
+ ),
+ )
diff --git a/python/l10n/fluent_migrations/bug_1835559_aboutDialog_explicit_textContent.py b/python/l10n/fluent_migrations/bug_1835559_aboutDialog_explicit_textContent.py
new file mode 100644
index 0000000000..1d73d62692
--- /dev/null
+++ b/python/l10n/fluent_migrations/bug_1835559_aboutDialog_explicit_textContent.py
@@ -0,0 +1,67 @@
+# Any copyright is dedicated to the Public Domain.
+# http://creativecommons.org/publicdomain/zero/1.0/
+
+import fluent.syntax.ast as FTL
+
+from fluent.migrate.transforms import TransformPattern
+
+
+class INSERT_VAR_IN_TAG(TransformPattern):
+ def visit_TextElement(self, node):
+ old_str = node.value
+ new_str = old_str
+ # update-downloading / update-downloading-message
+ new_str = new_str.replace(
+ '<label data-l10n-name="download-status"/>',
+ '<label data-l10n-name="download-status">{ $transfer }</label>',
+ )
+ # update-manual / update-internal-error
+ new_str = new_str.replace(
+ '<label data-l10n-name="manual-link"/>',
+ '<label data-l10n-name="manual-link">{ $displayUrl }</label>',
+ )
+ # aboutdialog-update-manual
+ new_str = new_str.replace(
+ '<a data-l10n-name="manual-link"/>',
+ '<a data-l10n-name="manual-link">{ $displayUrl }</a>',
+ )
+ if old_str == new_str and "$" not in old_str:
+ print("Warning: Failed to insert var in link in {}".format(old_str))
+ else:
+ node.value = new_str
+ return node
+
+
+def migrate(ctx):
+ """Bug 1835559, insert textContent var in a/label elements, part {index}."""
+
+ aboutDialog_ftl = "browser/browser/aboutDialog.ftl"
+ ctx.add_transforms(
+ aboutDialog_ftl,
+ aboutDialog_ftl,
+ [
+ FTL.Message(
+ id=FTL.Identifier("settings-update-downloading"),
+ value=INSERT_VAR_IN_TAG(aboutDialog_ftl, "update-downloading"),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("aboutdialog-update-downloading"),
+ value=INSERT_VAR_IN_TAG(aboutDialog_ftl, "update-downloading-message"),
+ ),
+ # Note: while we're renaming anyway: strip "aboutdialog-" prefix
+ # because it is used in main.inc.xhtml, not aboutDialog.xhtml.
+ FTL.Message(
+ id=FTL.Identifier("settings-update-manual-with-link"),
+ value=INSERT_VAR_IN_TAG(aboutDialog_ftl, "aboutdialog-update-manual"),
+ ),
+ # This is the actual update-manual message in aboutDialog.xhtml.
+ FTL.Message(
+ id=FTL.Identifier("aboutdialog-update-manual-with-link"),
+ value=INSERT_VAR_IN_TAG(aboutDialog_ftl, "update-manual"),
+ ),
+ FTL.Message(
+ id=FTL.Identifier("update-internal-error2"),
+ value=INSERT_VAR_IN_TAG(aboutDialog_ftl, "update-internal-error"),
+ ),
+ ],
+ )
diff --git a/python/l10n/fluent_migrations/bug_1866295_new_device_migration_strings.py b/python/l10n/fluent_migrations/bug_1866295_new_device_migration_strings.py
new file mode 100644
index 0000000000..a8ccb8c145
--- /dev/null
+++ b/python/l10n/fluent_migrations/bug_1866295_new_device_migration_strings.py
@@ -0,0 +1,22 @@
+# Any copyright is dedicated to the Public Domain.
+# http://creativecommons.org/publicdomain/zero/1.0/
+
+from fluent.migrate.helpers import transforms_from
+
+
+def migrate(ctx):
+ """Bug 1866295 - Land new strings for device migration ASRouter messages, part {index}."""
+
+ source = "browser/browser/newtab/asrouter.ftl"
+ target = source
+
+ ctx.add_transforms(
+ target,
+ target,
+ transforms_from(
+ """
+device-migration-fxa-spotlight-getting-new-device-primary-button = {COPY_PATTERN(from_path, "device-migration-fxa-spotlight-primary-button")}
+""",
+ from_path=source,
+ ),
+ )
diff --git a/python/l10n/fluent_migrations/bug_1867346_new_device_migration_string_replacement.py b/python/l10n/fluent_migrations/bug_1867346_new_device_migration_string_replacement.py
new file mode 100644
index 0000000000..a926bff41a
--- /dev/null
+++ b/python/l10n/fluent_migrations/bug_1867346_new_device_migration_string_replacement.py
@@ -0,0 +1,22 @@
+# Any copyright is dedicated to the Public Domain.
+# http://creativecommons.org/publicdomain/zero/1.0/
+
+from fluent.migrate.helpers import transforms_from
+
+
+def migrate(ctx):
+ """Bug 1867346 - Replace a string for device migration ASRouter messages, part {index}."""
+
+ source = "browser/browser/newtab/asrouter.ftl"
+ target = source
+
+ ctx.add_transforms(
+ target,
+ target,
+ transforms_from(
+ """
+device-migration-fxa-spotlight-getting-new-device-header-2 = {COPY_PATTERN(from_path, "fxa-sync-cfr-header")}
+""",
+ from_path=source,
+ ),
+ )