tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

commit 032930c7c7426846e41cd0488abd968be76279af
parent dabbf9a4cd16cb65fe410e0cd5e9232330db10f6
Author: Erik Nordin <enordin@mozilla.com>
Date:   Tue, 23 Dec 2025 16:05:29 +0000

Bug 2007194 - Migrate about:translations to moz-select r=translations-reviewers,gregtatum,fluent-reviewers,flod

This commit migrates the default HTML `<select>` elements
within the `about:translations` page to instead use the
reusable `moz-select` component.

Differential Revision: https://phabricator.services.mozilla.com/D277243

Diffstat:
Apython/l10n/fluent_migrations/bug_2007194_about_translations_label_attrs.py | 29+++++++++++++++++++++++++++++
Mtoolkit/components/translations/content/about-translations.css | 4+---
Mtoolkit/components/translations/content/about-translations.html | 25++++++++++++++++---------
Mtoolkit/components/translations/content/about-translations.mjs | 45+++++++++++++++++++++++++--------------------
Mtoolkit/components/translations/tests/browser/shared-head.js | 49+++++++++++++++++++++++++++----------------------
Mtoolkit/locales/en-US/toolkit/about/aboutTranslations.ftl | 9++++++---
6 files changed, 104 insertions(+), 57 deletions(-)

diff --git a/python/l10n/fluent_migrations/bug_2007194_about_translations_label_attrs.py b/python/l10n/fluent_migrations/bug_2007194_about_translations_label_attrs.py @@ -0,0 +1,29 @@ +# 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 2007194 - Migrate about:translations to moz-select, part {index}.""" + + source = "toolkit/toolkit/about/aboutTranslations.ftl" + target = source + + ctx.add_transforms( + target, + source, + transforms_from( + """ +about-translations-detect-default-label = + .label = { COPY_PATTERN(from_path, "about-translations-detect-default") } + +about-translations-detect-language-label = + .label = { COPY_PATTERN(from_path, "about-translations-detect-language") } + +about-translations-select-label = + .label = { COPY_PATTERN(from_path, "about-translations-select") } + """, + from_path=source, + ), + ) diff --git a/toolkit/components/translations/content/about-translations.css b/toolkit/components/translations/content/about-translations.css @@ -82,9 +82,7 @@ body { } .about-translations-select { - font-size: var(--font-size-large); - width: 100%; - margin: 0; + --select-min-height: var(--AT-square-button-large); } #about-translations-swap-languages-button { diff --git a/toolkit/components/translations/content/about-translations.html b/toolkit/components/translations/content/about-translations.html @@ -30,6 +30,10 @@ type="module" src="chrome://global/content/elements/moz-message-bar.mjs" ></script> + <script + type="module" + src="chrome://global/content/elements/moz-select.mjs" + ></script> </head> <body> @@ -84,17 +88,17 @@ </header> <section id="about-translations-main-user-interface"> - <select + <moz-select id="about-translations-source-select" class="about-translations-select" disabled > - <option - id="about-translations-detect-language-option" - data-l10n-id="about-translations-detect-default" + <moz-option + id="about-translations-detect-language-label-option" + data-l10n-id="about-translations-detect-default-label" value="detect" - ></option> - </select> + ></moz-option> + </moz-select> <moz-button id="about-translations-swap-languages-button" @@ -105,13 +109,16 @@ <div id="about-translations-swap-langauges-icon"></div> </moz-button> - <select + <moz-select id="about-translations-target-select" class="about-translations-select" disabled > - <option data-l10n-id="about-translations-select" value=""></option> - </select> + <moz-option + data-l10n-id="about-translations-select-label" + value="" + ></moz-option> + </moz-select> <div id="about-translations-source-section"> <textarea diff --git a/toolkit/components/translations/content/about-translations.mjs b/toolkit/components/translations/content/about-translations.mjs @@ -190,17 +190,17 @@ class AboutTranslations { * * @returns {{ * copyButton: HTMLElement, - * detectLanguageOption: HTMLOptionElement, + * detectLanguageOption: HTMLElement, * languageLoadErrorMessage: HTMLElement, * learnMoreLink: HTMLAnchorElement, * mainUserInterface: HTMLElement, - * sourceLanguageSelector: HTMLSelectElement, + * sourceLanguageSelector: HTMLElement, * sourceSection: HTMLElement, * sourceSectionActionsColumn: HTMLElement, * sourceSectionClearButton: HTMLElement, * sourceSectionTextArea: HTMLTextAreaElement, * swapLanguagesButton: HTMLElement, - * targetLanguageSelector: HTMLSelectElement, + * targetLanguageSelector: HTMLElement, * targetSection: HTMLElement, * targetSectionActionsRow: HTMLElement, * targetSectionTextArea: HTMLTextAreaElement, @@ -216,8 +216,10 @@ class AboutTranslations { copyButton: /** @type {HTMLElement} */ ( document.getElementById("about-translations-copy-button") ), - detectLanguageOption: /** @type {HTMLOptionElement} */ ( - document.getElementById("about-translations-detect-language-option") + detectLanguageOption: /** @type {HTMLElement} */ ( + document.getElementById( + "about-translations-detect-language-label-option" + ) ), languageLoadErrorMessage: /** @type {HTMLElement} */ ( document.getElementById( @@ -230,7 +232,7 @@ class AboutTranslations { mainUserInterface: /** @type {HTMLElement} */ ( document.getElementById("about-translations-main-user-interface") ), - sourceLanguageSelector: /** @type {HTMLSelectElement} */ ( + sourceLanguageSelector: /** @type {HTMLElement} */ ( document.getElementById("about-translations-source-select") ), sourceSection: /** @type {HTMLElement} */ ( @@ -248,7 +250,7 @@ class AboutTranslations { swapLanguagesButton: /** @type {HTMLElement} */ ( document.getElementById("about-translations-swap-languages-button") ), - targetLanguageSelector: /** @type {HTMLSelectElement} */ ( + targetLanguageSelector: /** @type {HTMLElement} */ ( document.getElementById("about-translations-target-select") ), targetSection: /** @type {HTMLElement} */ ( @@ -337,18 +339,18 @@ class AboutTranslations { for (const { langTagKey, displayName } of this.#supportedLanguages .sourceLanguages) { - const option = document.createElement("option"); + const option = document.createElement("moz-option"); option.value = langTagKey; - option.text = displayName; - sourceLanguageSelector.add(option); + option.setAttribute("label", displayName); + sourceLanguageSelector.append(option); } for (const { langTagKey, displayName } of this.#supportedLanguages .targetLanguages) { - const option = document.createElement("option"); + const option = document.createElement("moz-option"); option.value = langTagKey; - option.text = displayName; - targetLanguageSelector.add(option); + option.setAttribute("label", displayName); + targetLanguageSelector.append(option); } } @@ -359,6 +361,9 @@ class AboutTranslations { await this.#populateLanguageSelectors(); const { sourceLanguageSelector, targetLanguageSelector } = this.elements; + this.#resetDetectLanguageOptionText(); + sourceLanguageSelector.value = "detect"; + targetLanguageSelector.value = ""; sourceLanguageSelector.disabled = false; targetLanguageSelector.disabled = false; } @@ -383,7 +388,7 @@ class AboutTranslations { copyButton.addEventListener("click", this.#onCopyButton); learnMoreLink.addEventListener("click", this.#onLearnMoreLink); sourceLanguageSelector.addEventListener( - "input", + "change", this.#onSourceLanguageInput ); sourceSectionActionsColumn.addEventListener( @@ -406,7 +411,7 @@ class AboutTranslations { sourceSectionTextArea.addEventListener("blur", this.#onSourceTextAreaBlur); swapLanguagesButton.addEventListener("click", this.#onSwapLanguagesButton); targetLanguageSelector.addEventListener( - "input", + "change", this.#onTargetLanguageInput ); targetSectionTextArea.addEventListener( @@ -465,7 +470,7 @@ class AboutTranslations { }; /** - * Handles input events on the source-language selector. + * Handles change events on the source-language selector. */ #onSourceLanguageInput = () => { const { sourceLanguageSelector } = this.elements; @@ -482,7 +487,7 @@ class AboutTranslations { }; /** - * Handles input events on the target-language selector. + * Handles change events on the target-language selector. */ #onTargetLanguageInput = () => { this.#disableSwapLanguagesButton(); @@ -755,7 +760,7 @@ class AboutTranslations { } /** - * Sets the textContent of the about-translations-detect option in the + * Sets the label of the about-translations-detect option in the * about-translations-source-select dropdown. * * Passing an empty display name will reset to the default string. @@ -770,7 +775,7 @@ class AboutTranslations { detectLanguageOption.setAttribute("language", detectedLanguage); document.l10n.setAttributes( detectLanguageOption, - "about-translations-detect-language", + "about-translations-detect-language-label", { language: displayName } ); } @@ -784,7 +789,7 @@ class AboutTranslations { detectLanguageOption.removeAttribute("language"); document.l10n.setAttributes( detectLanguageOption, - "about-translations-detect-default" + "about-translations-detect-default-label" ); } diff --git a/toolkit/components/translations/tests/browser/shared-head.js b/toolkit/components/translations/tests/browser/shared-head.js @@ -204,9 +204,10 @@ async function openAboutTranslations({ const selectors = { pageHeader: "header#about-translations-header", mainUserInterface: "section#about-translations-main-user-interface", - sourceLanguageSelector: "select#about-translations-source-select", - targetLanguageSelector: "select#about-translations-target-select", - detectLanguageOption: "option#about-translations-detect-language-option", + sourceLanguageSelector: "moz-select#about-translations-source-select", + targetLanguageSelector: "moz-select#about-translations-target-select", + detectLanguageOption: + "moz-option#about-translations-detect-language-label-option", swapLanguagesButton: "moz-button#about-translations-swap-languages-button", sourceSectionTextArea: "textarea#about-translations-source-textarea", targetSectionTextArea: "textarea#about-translations-target-textarea", @@ -4431,11 +4432,13 @@ class AboutTranslationsTestUtils { try { await this.#runInPage( (selectors, { language }) => { - const selector = content.document.querySelector( - selectors.sourceLanguageSelector + const selector = Cu.waiveXrays( + content.document.querySelector(selectors.sourceLanguageSelector) ); selector.value = language; - selector.dispatchEvent(new content.Event("input")); + selector.dispatchEvent( + new content.Event("change", { bubbles: true }) + ); }, { language } ); @@ -4454,11 +4457,13 @@ class AboutTranslationsTestUtils { try { await this.#runInPage( (selectors, { language }) => { - const selector = content.document.querySelector( - selectors.targetLanguageSelector + const selector = Cu.waiveXrays( + content.document.querySelector(selectors.targetLanguageSelector) ); selector.value = language; - selector.dispatchEvent(new content.Event("input")); + selector.dispatchEvent( + new content.Event("change", { bubbles: true }) + ); }, { language } ); @@ -4865,16 +4870,16 @@ class AboutTranslationsTestUtils { let pageResult = {}; try { pageResult = await this.#runInPage(selectors => { - const selector = content.document.querySelector( - selectors.sourceLanguageSelector + const selector = Cu.waiveXrays( + content.document.querySelector(selectors.sourceLanguageSelector) ); const detectOptionElement = content.document.querySelector( selectors.detectLanguageOption ); return { actualValue: selector.value, - optionValues: Array.from(selector.options).map( - option => option.value + optionValues: Array.from(selector.querySelectorAll("moz-option")).map( + option => option.getAttribute("value") ), detectLanguageAttribute: detectOptionElement?.getAttribute("language") ?? null, @@ -4939,12 +4944,12 @@ class AboutTranslationsTestUtils { try { pageResult = await this.#runInPage( selectors => { - const selector = content.document.querySelector( - selectors.targetLanguageSelector - ); - const optionValues = Array.from(selector.options).map( - option => option.value + const selector = Cu.waiveXrays( + content.document.querySelector(selectors.targetLanguageSelector) ); + const optionValues = Array.from( + selector.querySelectorAll("moz-option") + ).map(option => option.getAttribute("value")); return { actualValue: selector.value, optionValues, @@ -5012,8 +5017,8 @@ class AboutTranslationsTestUtils { let pageResult = {}; try { pageResult = await this.#runInPage(selectors => { - const selector = content.document.querySelector( - selectors.sourceLanguageSelector + const selector = Cu.waiveXrays( + content.document.querySelector(selectors.sourceLanguageSelector) ); return { actualValue: selector.value }; }); @@ -5053,8 +5058,8 @@ class AboutTranslationsTestUtils { if (defaultValue !== undefined) { const expectedIdentifier = defaultValue - ? "about-translations-detect-default" - : "about-translations-detect-language"; + ? "about-translations-detect-default-label" + : "about-translations-detect-language-label"; is( localizationId, expectedIdentifier, diff --git a/toolkit/locales/en-US/toolkit/about/aboutTranslations.ftl b/toolkit/locales/en-US/toolkit/about/aboutTranslations.ftl @@ -27,13 +27,15 @@ about-translations-input-placeholder = # Text displayed on the source-language selector when no explicit option is selected # and no language has been identified from the content of the source-language text area. -about-translations-detect-default = Detect language +about-translations-detect-default-label = + .label = Detect language # Text displayed on the source-language selector when no explicit option is selected # and a valid language has been identified from the content of the source-language text area. # Variables: # $language (string) - The localized display name of the detected language -about-translations-detect-language = { $language } (detected) +about-translations-detect-language-label = + .label = { $language } (detected) # Placeholder text shown in the target-language output area when no translation has occurred. about-translations-output-placeholder = @@ -50,7 +52,8 @@ about-translations-copy-button-copied = .title = Copy translation # Text displayed on target-language selector when no language option is selected. -about-translations-select = Select language +about-translations-select-label = + .label = Select language # A message displayed in the target-language output area while waiting for the translation to complete. about-translations-translating-message = Translating…