Backed out 10 changesets (bug 1935511, bug 1936163, bug 1906608) for causing junit failures. CLOSED TREE
Backed out changeset ee1296ebe223 (bug 1936163) Backed out changeset 62586dda6137 (bug 1936163) Backed out changeset d897aec65319 (bug 1936163) Backed out changeset 8c5fe48bd7b9 (bug 1936163) Backed out changeset 9052f0459fc6 (bug 1936163) Backed out changeset 7b5c9db8ec47 (bug 1936163) Backed out changeset 2758b817c3b8 (bug 1935511) Backed out changeset cf8349221ae2 (bug 1935511) Backed out changeset b2b3c81ed886 (bug 1935511) Backed out changeset e7f67b975fd3 (bug 1906608)
This commit is contained in:
@@ -2577,11 +2577,12 @@ export class nsContextMenu {
|
||||
let displayName;
|
||||
|
||||
try {
|
||||
const languageDisplayNames =
|
||||
lazy.TranslationsParent.createLanguageDisplayNames();
|
||||
displayName = languageDisplayNames.of(toLanguage);
|
||||
const displayNames = new Services.intl.DisplayNames(undefined, {
|
||||
type: "language",
|
||||
});
|
||||
displayName = displayNames.of(toLanguage);
|
||||
} catch {
|
||||
// languageDisplayNames.of threw, do nothing.
|
||||
// Services.intl.DisplayNames.of threw, do nothing.
|
||||
}
|
||||
|
||||
if (displayName) {
|
||||
|
||||
@@ -543,7 +543,7 @@ let gTranslationsPane = {
|
||||
|
||||
// When the preferences is opened for the first time
|
||||
// the translations settings HTML page is initialized with
|
||||
// the existing settings by adding all languages from the latest preferences
|
||||
// the exisitng settings by adding all languages from the latest preferences
|
||||
for (const lang of added) {
|
||||
this.addTranslateLanguage(lang, languageList, prefix);
|
||||
// if a language is added to Always translate list,
|
||||
@@ -743,19 +743,9 @@ let gTranslationsPane = {
|
||||
*/
|
||||
addTranslateLanguage(langTag, languageList, translatePrefix) {
|
||||
// While adding the first language, add the Header and language List div
|
||||
const languageDisplayNames =
|
||||
TranslationsParent.createLanguageDisplayNames();
|
||||
|
||||
let languageDisplayName;
|
||||
try {
|
||||
languageDisplayName = languageDisplayNames.of(langTag);
|
||||
} catch (error) {
|
||||
console.warn(
|
||||
`Failed to retrieve language display name for '${langTag}'.`
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
const languageDisplayName =
|
||||
TranslationsParent.getLanguageDisplayName(langTag);
|
||||
const languageLabel = this.createLangLabel(
|
||||
languageDisplayName,
|
||||
langTag,
|
||||
@@ -965,13 +955,10 @@ let gTranslationsPane = {
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
|
||||
const languageDisplayNames =
|
||||
TranslationsParent.createLanguageDisplayNames();
|
||||
|
||||
this.showErrorMessage(
|
||||
eventButton.parentNode,
|
||||
"translations-settings-language-download-error",
|
||||
languageDisplayNames.of(langTag)
|
||||
TranslationsParent.getLanguageDisplayName(langTag)
|
||||
);
|
||||
const hasAllFilesForLanguage =
|
||||
await TranslationsParent.hasAllFilesForLanguage(langTag);
|
||||
@@ -1031,14 +1018,10 @@ let gTranslationsPane = {
|
||||
} catch (error) {
|
||||
// The download phases are invalidated with the error and must be reloaded.
|
||||
console.error(error);
|
||||
|
||||
const languageDisplayNames =
|
||||
TranslationsParent.createLanguageDisplayNames();
|
||||
|
||||
this.showErrorMessage(
|
||||
eventButton.parentNode,
|
||||
"translations-settings-language-remove-error",
|
||||
languageDisplayNames.of(langTag)
|
||||
TranslationsParent.getLanguageDisplayName(langTag)
|
||||
);
|
||||
const hasAllFilesForLanguage =
|
||||
await TranslationsParent.hasAllFilesForLanguage(langTag);
|
||||
|
||||
@@ -14,8 +14,6 @@ ChromeUtils.defineESModuleGetters(this, {
|
||||
PageActions: "resource:///modules/PageActions.sys.mjs",
|
||||
TranslationsTelemetry:
|
||||
"chrome://browser/content/translations/TranslationsTelemetry.sys.mjs",
|
||||
TranslationsUtils:
|
||||
"chrome://global/content/translations/TranslationsUtils.sys.mjs",
|
||||
TranslationsPanelShared:
|
||||
"chrome://browser/content/translations/TranslationsPanelShared.sys.mjs",
|
||||
});
|
||||
@@ -447,14 +445,8 @@ var FullPageTranslationsPanel = new (class {
|
||||
if (
|
||||
requestedTranslationPair &&
|
||||
!isEngineReady &&
|
||||
TranslationsUtils.langTagsMatch(
|
||||
fromMenuList.value,
|
||||
requestedTranslationPair.fromLanguage
|
||||
) &&
|
||||
TranslationsUtils.langTagsMatch(
|
||||
toMenuList.value,
|
||||
requestedTranslationPair.toLanguage
|
||||
)
|
||||
toMenuList.value === requestedTranslationPair.toLanguage &&
|
||||
fromMenuList.value === requestedTranslationPair.fromLanguage
|
||||
) {
|
||||
// A translation has been requested, but is not ready yet.
|
||||
document.l10n.setAttributes(
|
||||
@@ -470,34 +462,29 @@ var FullPageTranslationsPanel = new (class {
|
||||
"translations-panel-translate-button"
|
||||
);
|
||||
translateButton.disabled =
|
||||
// The translation languages are the same, don't allow this translation.
|
||||
toMenuList.value === fromMenuList.value ||
|
||||
// No "to" language was provided.
|
||||
!toMenuList.value ||
|
||||
// No "from" language was provided.
|
||||
!fromMenuList.value ||
|
||||
// The translation languages are the same, don't allow this translation.
|
||||
TranslationsUtils.langTagsMatch(toMenuList.value, fromMenuList.value) ||
|
||||
// This is the requested translation pair.
|
||||
(requestedTranslationPair &&
|
||||
TranslationsUtils.langTagsMatch(
|
||||
requestedTranslationPair.fromLanguage,
|
||||
fromMenuList.value
|
||||
) &&
|
||||
TranslationsUtils.langTagsMatch(
|
||||
requestedTranslationPair.toLanguage,
|
||||
toMenuList.value
|
||||
));
|
||||
requestedTranslationPair.fromLanguage === fromMenuList.value &&
|
||||
requestedTranslationPair.toLanguage === toMenuList.value);
|
||||
}
|
||||
|
||||
if (requestedTranslationPair && isEngineReady) {
|
||||
const { fromLanguage, toLanguage } = requestedTranslationPair;
|
||||
const languageDisplayNames =
|
||||
TranslationsParent.createLanguageDisplayNames();
|
||||
const displayNames = new Services.intl.DisplayNames(undefined, {
|
||||
type: "language",
|
||||
});
|
||||
cancelButton.hidden = true;
|
||||
this.updateUIForReTranslation(true /* isReTranslation */);
|
||||
|
||||
document.l10n.setAttributes(header, "translations-panel-revisit-header", {
|
||||
fromLanguage: languageDisplayNames.of(fromLanguage),
|
||||
toLanguage: languageDisplayNames.of(toLanguage),
|
||||
fromLanguage: displayNames.of(fromLanguage),
|
||||
toLanguage: displayNames.of(toLanguage),
|
||||
});
|
||||
} else {
|
||||
document.l10n.setAttributes(header, "translations-panel-header");
|
||||
@@ -625,9 +612,7 @@ var FullPageTranslationsPanel = new (class {
|
||||
});
|
||||
}
|
||||
|
||||
if (
|
||||
TranslationsUtils.langTagsMatch(fromMenuList.value, toMenuList.value)
|
||||
) {
|
||||
if (fromMenuList.value === toMenuList.value) {
|
||||
// The best possible user-preferred language tag that we were able to find for the
|
||||
// toMenuList is the same as the fromMenuList, but same-language to same-language
|
||||
// translations are not allowed in Full Page Translations, so we will just show the
|
||||
@@ -669,11 +654,11 @@ var FullPageTranslationsPanel = new (class {
|
||||
);
|
||||
let language;
|
||||
if (docLangTag) {
|
||||
const languageDisplayNames =
|
||||
TranslationsParent.createLanguageDisplayNames({
|
||||
fallback: "none",
|
||||
});
|
||||
language = languageDisplayNames.of(docLangTag);
|
||||
const displayNames = new Intl.DisplayNames(undefined, {
|
||||
type: "language",
|
||||
fallback: "none",
|
||||
});
|
||||
language = displayNames.of(docLangTag);
|
||||
}
|
||||
if (language) {
|
||||
document.l10n.setAttributes(
|
||||
@@ -795,12 +780,12 @@ var FullPageTranslationsPanel = new (class {
|
||||
/** @type {string | undefined} */
|
||||
let docLangDisplayName;
|
||||
if (docLangTag) {
|
||||
const languageDisplayNames =
|
||||
TranslationsParent.createLanguageDisplayNames({
|
||||
fallback: "none",
|
||||
});
|
||||
const displayNames = new Services.intl.DisplayNames(undefined, {
|
||||
type: "language",
|
||||
fallback: "none",
|
||||
});
|
||||
// The display name will still be empty if the docLangTag is not known.
|
||||
docLangDisplayName = languageDisplayNames.of(docLangTag);
|
||||
docLangDisplayName = displayNames.of(docLangTag);
|
||||
}
|
||||
|
||||
for (const menuitem of alwaysTranslateMenuItems) {
|
||||
@@ -1592,26 +1577,26 @@ var FullPageTranslationsPanel = new (class {
|
||||
// The translation is active, update the urlbar button.
|
||||
button.setAttribute("translationsactive", true);
|
||||
if (isEngineReady) {
|
||||
const languageDisplayNames =
|
||||
TranslationsParent.createLanguageDisplayNames();
|
||||
const displayNames = new Services.intl.DisplayNames(undefined, {
|
||||
type: "language",
|
||||
});
|
||||
|
||||
document.l10n.setAttributes(
|
||||
button,
|
||||
"urlbar-translations-button-translated",
|
||||
{
|
||||
fromLanguage: languageDisplayNames.of(
|
||||
fromLanguage: displayNames.of(
|
||||
requestedTranslationPair.fromLanguage
|
||||
),
|
||||
toLanguage: languageDisplayNames.of(
|
||||
toLanguage: displayNames.of(
|
||||
requestedTranslationPair.toLanguage
|
||||
),
|
||||
}
|
||||
);
|
||||
// Show the language tag of translated the page in the button.
|
||||
// Show the locale of the page in the button.
|
||||
buttonLocale.hidden = false;
|
||||
buttonCircleArrows.hidden = true;
|
||||
buttonLocale.innerText =
|
||||
requestedTranslationPair.toLanguage.split("-")[0];
|
||||
buttonLocale.innerText = requestedTranslationPair.toLanguage;
|
||||
} else {
|
||||
document.l10n.setAttributes(
|
||||
button,
|
||||
|
||||
@@ -311,15 +311,11 @@ var SelectTranslationsPanel = new (class {
|
||||
// First see if any of the detected languages are supported and return it if so.
|
||||
const { language, languages } =
|
||||
await LanguageDetector.detectLanguage(textToTranslate);
|
||||
const languagePairs = await TranslationsParent.getLanguagePairs();
|
||||
for (const { languageCode } of languages) {
|
||||
const compatibleLangTag =
|
||||
TranslationsParent.findCompatibleSourceLangTagSync(
|
||||
languageCode,
|
||||
languagePairs
|
||||
);
|
||||
if (compatibleLangTag) {
|
||||
return compatibleLangTag;
|
||||
const isSupported =
|
||||
await TranslationsParent.isSupportedAsFromLang(languageCode);
|
||||
if (isSupported) {
|
||||
return languageCode;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -464,16 +460,16 @@ var SelectTranslationsPanel = new (class {
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async #initializeLanguageMenuList(langTag, menuList) {
|
||||
const compatibleLangTag =
|
||||
const isLangTagSupported =
|
||||
menuList.id === this.elements.fromMenuList.id
|
||||
? await TranslationsParent.findCompatibleSourceLangTag(langTag)
|
||||
: await TranslationsParent.findCompatibleTargetLangTag(langTag);
|
||||
? await TranslationsParent.isSupportedAsFromLang(langTag)
|
||||
: await TranslationsParent.isSupportedAsToLang(langTag);
|
||||
|
||||
if (compatibleLangTag) {
|
||||
if (isLangTagSupported) {
|
||||
// Remove the data-l10n-id because the menulist label will
|
||||
// be populated from the supported language's display name.
|
||||
menuList.removeAttribute("data-l10n-id");
|
||||
menuList.value = compatibleLangTag;
|
||||
menuList.value = langTag;
|
||||
} else {
|
||||
await this.#deselectLanguage(menuList);
|
||||
}
|
||||
@@ -724,13 +720,13 @@ var SelectTranslationsPanel = new (class {
|
||||
async #registerSourceText(sourceText, langPairPromise) {
|
||||
const { textArea } = this.elements;
|
||||
const { fromLanguage, toLanguage } = await langPairPromise;
|
||||
const compatibleFromLang =
|
||||
await TranslationsParent.findCompatibleSourceLangTag(fromLanguage);
|
||||
const isFromLangSupported =
|
||||
await TranslationsParent.isSupportedAsFromLang(fromLanguage);
|
||||
|
||||
if (compatibleFromLang) {
|
||||
if (isFromLangSupported) {
|
||||
this.#changeStateTo("idle", /* retainEntries */ false, {
|
||||
sourceText,
|
||||
fromLanguage: compatibleFromLang,
|
||||
fromLanguage,
|
||||
toLanguage,
|
||||
});
|
||||
} else {
|
||||
@@ -2134,10 +2130,11 @@ var SelectTranslationsPanel = new (class {
|
||||
|
||||
const { unsupportedLanguageMessageBar, tryAnotherSourceMenuList } =
|
||||
this.elements;
|
||||
const languageDisplayNames =
|
||||
TranslationsParent.createLanguageDisplayNames();
|
||||
const displayNames = new Services.intl.DisplayNames(undefined, {
|
||||
type: "language",
|
||||
});
|
||||
try {
|
||||
const language = languageDisplayNames.of(detectedLanguage);
|
||||
const language = displayNames.of(detectedLanguage);
|
||||
if (language) {
|
||||
document.l10n.setAttributes(
|
||||
unsupportedLanguageMessageBar,
|
||||
|
||||
@@ -93,8 +93,6 @@ skip-if = ["true"]
|
||||
|
||||
["browser_translations_full_page_panel_retry.js"]
|
||||
|
||||
["browser_translations_full_page_panel_script_tags.js"]
|
||||
|
||||
["browser_translations_full_page_panel_settings_unsupported_lang.js"]
|
||||
|
||||
["browser_translations_full_page_panel_switch_languages.js"]
|
||||
@@ -185,8 +183,6 @@ skip-if = ["true"]
|
||||
|
||||
["browser_translations_select_panel_retranslate_on_change_language_from_dropdown_menu.js"]
|
||||
|
||||
["browser_translations_select_panel_script_tags.js"]
|
||||
|
||||
["browser_translations_select_panel_select_current_language_directly.js"]
|
||||
|
||||
["browser_translations_select_panel_select_current_language_from_dropdown_menu.js"]
|
||||
|
||||
@@ -36,20 +36,13 @@ add_task(async function test_translations_engine_destroy() {
|
||||
await EngineProcess.destroyTranslationsEngine();
|
||||
|
||||
info("Mutate the page's content to re-trigger a translation.");
|
||||
const { promise: animationPromise, resolve } = Promise.withResolvers();
|
||||
requestAnimationFrame(() => {
|
||||
requestAnimationFrame(resolve);
|
||||
});
|
||||
|
||||
await runInPage(async TranslationsTest => {
|
||||
const { getH1 } = TranslationsTest.getSelectors();
|
||||
getH1().innerText = "New text for the H1";
|
||||
});
|
||||
|
||||
await animationPromise;
|
||||
|
||||
info("The engine downloads should be requested again.");
|
||||
await resolveDownloads(1);
|
||||
resolveDownloads(1);
|
||||
|
||||
await runInPage(async TranslationsTest => {
|
||||
const { getH1 } = TranslationsTest.getSelectors();
|
||||
|
||||
@@ -47,21 +47,18 @@ add_task(async function test_translations_engine_destroy_pending() {
|
||||
await EngineProcess.destroyTranslationsEngine();
|
||||
|
||||
info("Mutate the page's content to re-trigger a translation.");
|
||||
const { promise: animationPromise, resolve } = Promise.withResolvers();
|
||||
requestAnimationFrame(() => {
|
||||
requestAnimationFrame(resolve);
|
||||
});
|
||||
|
||||
await runInPage(async TranslationsTest => {
|
||||
const { getH1 } = TranslationsTest.getSelectors();
|
||||
getH1().innerText = "New text for the H1";
|
||||
});
|
||||
|
||||
await animationPromise;
|
||||
info("Wait for a second to ensure the mutation takes.");
|
||||
await TestUtils.waitForTick();
|
||||
|
||||
await switchTab(spanishTab, "spanish tab");
|
||||
|
||||
info("The engine downloads should be requested again.");
|
||||
await resolveDownloads(1);
|
||||
resolveDownloads(1);
|
||||
|
||||
await runInPage(async TranslationsTest => {
|
||||
const { getH1 } = TranslationsTest.getSelectors();
|
||||
|
||||
@@ -1,151 +0,0 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
https://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
* This test case verifies the behavior of the FullPageTranslationsPanel when the source
|
||||
* language has a script tag and the target language does not have a script tag.
|
||||
*/
|
||||
add_task(async function test_translations_panel_source_lang_has_script_tag() {
|
||||
const { cleanup, resolveDownloads, runInPage } = await loadTestPage({
|
||||
page: SPANISH_PAGE_URL,
|
||||
languagePairs: [
|
||||
{ fromLang: "es", toLang: "en" },
|
||||
{ fromLang: "en", toLang: "es" },
|
||||
{ fromLang: "zh-Hans", toLang: "en" },
|
||||
],
|
||||
});
|
||||
|
||||
await FullPageTranslationsTestUtils.assertTranslationsButton(
|
||||
{ button: true },
|
||||
"The button is available."
|
||||
);
|
||||
|
||||
await FullPageTranslationsTestUtils.assertPageIsUntranslated(runInPage);
|
||||
|
||||
await FullPageTranslationsTestUtils.openPanel({
|
||||
expectedFromLanguage: "es",
|
||||
expectedToLanguage: "en",
|
||||
onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewDefault,
|
||||
});
|
||||
|
||||
await FullPageTranslationsTestUtils.changeSelectedFromLanguage({
|
||||
langTag: "zh-Hans",
|
||||
});
|
||||
|
||||
await FullPageTranslationsTestUtils.changeSelectedToLanguage({
|
||||
langTag: "es",
|
||||
});
|
||||
|
||||
await FullPageTranslationsTestUtils.clickTranslateButton({
|
||||
downloadHandler: resolveDownloads,
|
||||
pivotTranslation: true,
|
||||
});
|
||||
|
||||
await FullPageTranslationsTestUtils.assertPageIsTranslated({
|
||||
fromLanguage: "zh-Hans",
|
||||
toLanguage: "es",
|
||||
runInPage,
|
||||
});
|
||||
|
||||
await cleanup();
|
||||
});
|
||||
|
||||
/**
|
||||
* This test case verifies the behavior of the FullPageTranslationsPanel when the target
|
||||
* language has a script tag and the source language does not have a script tag.
|
||||
*/
|
||||
add_task(async function test_translations_panel_target_lang_has_script_tag() {
|
||||
const { cleanup, resolveDownloads, runInPage } = await loadTestPage({
|
||||
page: SPANISH_PAGE_URL,
|
||||
languagePairs: [
|
||||
{ fromLang: "es", toLang: "en" },
|
||||
{ fromLang: "en", toLang: "es" },
|
||||
{ fromLang: "en", toLang: "zh-Hant" },
|
||||
],
|
||||
});
|
||||
|
||||
await FullPageTranslationsTestUtils.assertTranslationsButton(
|
||||
{ button: true },
|
||||
"The button is available."
|
||||
);
|
||||
|
||||
await FullPageTranslationsTestUtils.assertPageIsUntranslated(runInPage);
|
||||
|
||||
await FullPageTranslationsTestUtils.openPanel({
|
||||
expectedFromLanguage: "es",
|
||||
expectedToLanguage: "en",
|
||||
onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewDefault,
|
||||
});
|
||||
|
||||
await FullPageTranslationsTestUtils.changeSelectedToLanguage({
|
||||
langTag: "zh-Hant",
|
||||
});
|
||||
|
||||
await FullPageTranslationsTestUtils.clickTranslateButton({
|
||||
downloadHandler: resolveDownloads,
|
||||
pivotTranslation: true,
|
||||
});
|
||||
|
||||
await FullPageTranslationsTestUtils.assertPageIsTranslated({
|
||||
fromLanguage: "es",
|
||||
toLanguage: "zh-Hant",
|
||||
runInPage,
|
||||
});
|
||||
|
||||
await cleanup();
|
||||
});
|
||||
|
||||
/**
|
||||
* This test case verifies the behavior of the FullPageTranslationsPanel when both the source
|
||||
* language and the target language have a script tag.
|
||||
*/
|
||||
add_task(
|
||||
async function test_translations_panel_source_and_target_langs_have_script_tags() {
|
||||
const { cleanup, resolveDownloads, runInPage } = await loadTestPage({
|
||||
page: SPANISH_PAGE_URL,
|
||||
languagePairs: [
|
||||
{ fromLang: "es", toLang: "en" },
|
||||
{ fromLang: "en", toLang: "es" },
|
||||
{ fromLang: "zh-Hans", toLang: "en" },
|
||||
{ fromLang: "en", toLang: "zh-Hans" },
|
||||
{ fromLang: "zh-Hant", toLang: "en" },
|
||||
{ fromLang: "en", toLang: "zh-Hant" },
|
||||
],
|
||||
});
|
||||
|
||||
await FullPageTranslationsTestUtils.assertTranslationsButton(
|
||||
{ button: true },
|
||||
"The button is available."
|
||||
);
|
||||
|
||||
await FullPageTranslationsTestUtils.assertPageIsUntranslated(runInPage);
|
||||
|
||||
await FullPageTranslationsTestUtils.openPanel({
|
||||
expectedFromLanguage: "es",
|
||||
expectedToLanguage: "en",
|
||||
onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewDefault,
|
||||
});
|
||||
|
||||
await FullPageTranslationsTestUtils.changeSelectedFromLanguage({
|
||||
langTag: "zh-Hant",
|
||||
});
|
||||
await FullPageTranslationsTestUtils.changeSelectedToLanguage({
|
||||
langTag: "zh-Hans",
|
||||
});
|
||||
|
||||
await FullPageTranslationsTestUtils.clickTranslateButton({
|
||||
downloadHandler: resolveDownloads,
|
||||
pivotTranslation: true,
|
||||
});
|
||||
|
||||
await FullPageTranslationsTestUtils.assertPageIsTranslated({
|
||||
fromLanguage: "zh-Hant",
|
||||
toLanguage: "zh-Hans",
|
||||
runInPage,
|
||||
});
|
||||
|
||||
await cleanup();
|
||||
}
|
||||
);
|
||||
@@ -86,7 +86,7 @@ add_task(async function test_translations_telemetry_retranslate() {
|
||||
to_language: "en",
|
||||
auto_translate: false,
|
||||
document_language: "es",
|
||||
top_preferred_language: "en-US",
|
||||
top_preferred_language: "en",
|
||||
request_target: "full_page",
|
||||
},
|
||||
}
|
||||
|
||||
@@ -126,7 +126,7 @@ add_task(
|
||||
to_language: "en",
|
||||
auto_translate: false,
|
||||
document_language: "es",
|
||||
top_preferred_language: "en-US",
|
||||
top_preferred_language: "en",
|
||||
request_target: "full_page",
|
||||
},
|
||||
}
|
||||
@@ -205,7 +205,7 @@ add_task(async function test_translations_telemetry_auto_translation_failure() {
|
||||
to_language: "en",
|
||||
auto_translate: true,
|
||||
document_language: "es",
|
||||
top_preferred_language: "en-US",
|
||||
top_preferred_language: "en",
|
||||
request_target: "full_page",
|
||||
},
|
||||
}
|
||||
|
||||
@@ -106,7 +106,7 @@ add_task(async function test_translations_telemetry_manual_translation() {
|
||||
to_language: "en",
|
||||
auto_translate: false,
|
||||
document_language: "es",
|
||||
top_preferred_language: "en-US",
|
||||
top_preferred_language: "en",
|
||||
request_target: "full_page",
|
||||
},
|
||||
}
|
||||
@@ -178,7 +178,7 @@ add_task(async function test_translations_telemetry_auto_translation() {
|
||||
to_language: "en",
|
||||
auto_translate: true,
|
||||
document_language: "es",
|
||||
top_preferred_language: "en-US",
|
||||
top_preferred_language: "en",
|
||||
request_target: "full_page",
|
||||
},
|
||||
}
|
||||
|
||||
@@ -192,7 +192,7 @@ add_task(async function test_translations_telemetry_unsupported_lang() {
|
||||
to_language: "en",
|
||||
auto_translate: false,
|
||||
document_language: "es",
|
||||
top_preferred_language: "en-US",
|
||||
top_preferred_language: "en",
|
||||
request_target: "full_page",
|
||||
},
|
||||
}
|
||||
|
||||
@@ -22,11 +22,6 @@ add_task(
|
||||
{ fromLang: "fi", toLang: "en" },
|
||||
// Only supported as a target language
|
||||
{ fromLang: "en", toLang: "sl" },
|
||||
// Languages with script tags
|
||||
{ fromLang: "zh-Hans", toLang: "en" },
|
||||
{ fromLang: "en", toLang: "zh-Hans" },
|
||||
{ fromLang: "zh-Hant", toLang: "en" },
|
||||
{ fromLang: "en", toLang: "zh-Hant" },
|
||||
],
|
||||
prefs: [["browser.translations.select.enable", true]],
|
||||
});
|
||||
@@ -35,72 +30,36 @@ add_task(
|
||||
|
||||
await SelectTranslationsTestUtils.testContextMenuItemWithLocales({
|
||||
runInPage,
|
||||
appLocales: ["es", "fr", "fi", "ja", "sl"],
|
||||
appLocales: ["es", "fr", "fi", "zh", "sl"],
|
||||
// The page language tag is "es", so expect the next language in the list.
|
||||
expectedTargetLanguage: "fr",
|
||||
});
|
||||
|
||||
await SelectTranslationsTestUtils.testContextMenuItemWithLocales({
|
||||
runInPage,
|
||||
appLocales: ["fr", "fi", "ja", "sl", "es"],
|
||||
appLocales: ["fr", "fi", "zh", "sl", "es"],
|
||||
expectedTargetLanguage: "fr",
|
||||
});
|
||||
|
||||
await SelectTranslationsTestUtils.testContextMenuItemWithLocales({
|
||||
runInPage,
|
||||
appLocales: ["fi", "ja", "sl", "es", "fr"],
|
||||
appLocales: ["fi", "zh", "sl", "es", "fr"],
|
||||
// "fi" is not supported as a target language, so fall back
|
||||
expectedTargetLanguage: "sl",
|
||||
});
|
||||
|
||||
await SelectTranslationsTestUtils.testContextMenuItemWithLocales({
|
||||
runInPage,
|
||||
appLocales: ["ja", "sl", "es", "fr", "fi"],
|
||||
appLocales: ["zh", "sl", "es", "fr", "fi"],
|
||||
expectedTargetLanguage: "sl",
|
||||
});
|
||||
|
||||
await SelectTranslationsTestUtils.testContextMenuItemWithLocales({
|
||||
runInPage,
|
||||
appLocales: ["sl", "es", "fr", "fi", "ja"],
|
||||
appLocales: ["sl", "es", "fr", "fi", "zh"],
|
||||
expectedTargetLanguage: "sl",
|
||||
});
|
||||
|
||||
await SelectTranslationsTestUtils.testContextMenuItemWithLocales({
|
||||
runInPage,
|
||||
appLocales: ["zh-CN", "zh", "es", "fr", "fi", "ja"],
|
||||
expectedTargetLanguage: "zh-Hans",
|
||||
});
|
||||
|
||||
await SelectTranslationsTestUtils.testContextMenuItemWithLocales({
|
||||
runInPage,
|
||||
appLocales: ["zh-SG", "zh", "es", "fr", "fi", "ja"],
|
||||
expectedTargetLanguage: "zh-Hans",
|
||||
});
|
||||
|
||||
await SelectTranslationsTestUtils.testContextMenuItemWithLocales({
|
||||
runInPage,
|
||||
appLocales: ["zh-MY", "zh", "es", "fr", "fi", "ja"],
|
||||
expectedTargetLanguage: "zh-Hans",
|
||||
});
|
||||
|
||||
await SelectTranslationsTestUtils.testContextMenuItemWithLocales({
|
||||
runInPage,
|
||||
appLocales: ["zh-HK", "zh", "es", "fr", "fi", "ja"],
|
||||
expectedTargetLanguage: "zh-Hant",
|
||||
});
|
||||
|
||||
await SelectTranslationsTestUtils.testContextMenuItemWithLocales({
|
||||
runInPage,
|
||||
appLocales: ["zh-MO", "zh", "es", "fr", "fi", "ja"],
|
||||
expectedTargetLanguage: "zh-Hant",
|
||||
});
|
||||
|
||||
await SelectTranslationsTestUtils.testContextMenuItemWithLocales({
|
||||
runInPage,
|
||||
appLocales: ["zh-TW", "zh", "es", "fr", "fi", "ja"],
|
||||
expectedTargetLanguage: "zh-Hant",
|
||||
});
|
||||
|
||||
await cleanup();
|
||||
}
|
||||
);
|
||||
|
||||
@@ -1,126 +0,0 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
https://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
* This test case verifies the behavior of the SelectTranslationsPanel when the source
|
||||
* language has a script tag and the target language does not have a script tag.
|
||||
*/
|
||||
add_task(
|
||||
async function test_select_translations_panel_source_lang_has_script_tag() {
|
||||
const { cleanup, runInPage, resolveDownloads } = await loadTestPage({
|
||||
page: SELECT_TEST_PAGE_URL,
|
||||
languagePairs: [
|
||||
{ fromLang: "es", toLang: "en" },
|
||||
{ fromLang: "en", toLang: "es" },
|
||||
{ fromLang: "zh-Hant", toLang: "en" },
|
||||
],
|
||||
prefs: [["browser.translations.select.enable", true]],
|
||||
});
|
||||
|
||||
await SelectTranslationsTestUtils.openPanel(runInPage, {
|
||||
selectSpanishSentence: true,
|
||||
openAtSpanishSentence: true,
|
||||
expectedFromLanguage: "es",
|
||||
expectedToLanguage: "en",
|
||||
downloadHandler: resolveDownloads,
|
||||
onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated,
|
||||
});
|
||||
|
||||
await SelectTranslationsTestUtils.changeSelectedFromLanguage(["zh-Hant"], {
|
||||
openDropdownMenu: false,
|
||||
downloadHandler: resolveDownloads,
|
||||
onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated,
|
||||
});
|
||||
|
||||
await SelectTranslationsTestUtils.clickDoneButton();
|
||||
|
||||
await cleanup();
|
||||
}
|
||||
);
|
||||
|
||||
/**
|
||||
* This test case verifies the behavior of the SelectTranslationsPanel when the target
|
||||
* language has a script tag and the source language does not have a script tag.
|
||||
*/
|
||||
add_task(
|
||||
async function test_select_translations_panel_target_lang_has_script_tag() {
|
||||
const { cleanup, runInPage, resolveDownloads } = await loadTestPage({
|
||||
page: SELECT_TEST_PAGE_URL,
|
||||
languagePairs: [
|
||||
{ fromLang: "es", toLang: "en" },
|
||||
{ fromLang: "en", toLang: "es" },
|
||||
{ fromLang: "en", toLang: "zh-Hans" },
|
||||
],
|
||||
prefs: [["browser.translations.select.enable", true]],
|
||||
});
|
||||
|
||||
await SelectTranslationsTestUtils.openPanel(runInPage, {
|
||||
selectSpanishSentence: true,
|
||||
openAtSpanishSentence: true,
|
||||
expectedFromLanguage: "es",
|
||||
expectedToLanguage: "en",
|
||||
downloadHandler: resolveDownloads,
|
||||
onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated,
|
||||
});
|
||||
|
||||
await SelectTranslationsTestUtils.changeSelectedToLanguage(["zh-Hans"], {
|
||||
openDropdownMenu: true,
|
||||
downloadHandler: resolveDownloads,
|
||||
pivotTranslation: true,
|
||||
onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated,
|
||||
});
|
||||
|
||||
await SelectTranslationsTestUtils.clickDoneButton();
|
||||
|
||||
await cleanup();
|
||||
}
|
||||
);
|
||||
|
||||
/**
|
||||
* This test case verifies the behavior of the SelectTranslationsPanel when both the source
|
||||
* language and the target language have a script tag.
|
||||
*/
|
||||
add_task(
|
||||
async function test_select_translations_panel_source_and_target_langs_have_script_tags() {
|
||||
const { cleanup, runInPage, resolveDownloads } = await loadTestPage({
|
||||
page: SELECT_TEST_PAGE_URL,
|
||||
languagePairs: [
|
||||
{ fromLang: "es", toLang: "en" },
|
||||
{ fromLang: "en", toLang: "es" },
|
||||
{ fromLang: "zh-Hans", toLang: "en" },
|
||||
{ fromLang: "en", toLang: "zh-Hans" },
|
||||
{ fromLang: "zh-Hant", toLang: "en" },
|
||||
{ fromLang: "en", toLang: "zh-Hant" },
|
||||
],
|
||||
prefs: [["browser.translations.select.enable", true]],
|
||||
});
|
||||
|
||||
await SelectTranslationsTestUtils.openPanel(runInPage, {
|
||||
selectSpanishSentence: true,
|
||||
openAtSpanishSentence: true,
|
||||
expectedFromLanguage: "es",
|
||||
expectedToLanguage: "en",
|
||||
downloadHandler: resolveDownloads,
|
||||
onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated,
|
||||
});
|
||||
|
||||
await SelectTranslationsTestUtils.changeSelectedFromLanguage(["zh-Hant"], {
|
||||
openDropdownMenu: false,
|
||||
downloadHandler: resolveDownloads,
|
||||
onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated,
|
||||
});
|
||||
|
||||
await SelectTranslationsTestUtils.changeSelectedToLanguage(["zh-Hans"], {
|
||||
openDropdownMenu: true,
|
||||
downloadHandler: resolveDownloads,
|
||||
pivotTranslation: true,
|
||||
onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated,
|
||||
});
|
||||
|
||||
await SelectTranslationsTestUtils.clickDoneButton();
|
||||
|
||||
await cleanup();
|
||||
}
|
||||
);
|
||||
@@ -52,7 +52,7 @@ add_task(
|
||||
document_language: "es",
|
||||
from_language: "es",
|
||||
to_language: "en",
|
||||
top_preferred_language: "en-US",
|
||||
top_preferred_language: "en",
|
||||
text_source: "selection",
|
||||
},
|
||||
}
|
||||
@@ -72,7 +72,7 @@ add_task(
|
||||
document_language: "es",
|
||||
from_language: "es",
|
||||
to_language: "en",
|
||||
top_preferred_language: "en-US",
|
||||
top_preferred_language: "en",
|
||||
request_target: "select",
|
||||
auto_translate: false,
|
||||
source_text_code_units: 165,
|
||||
@@ -151,7 +151,7 @@ add_task(
|
||||
document_language: "es",
|
||||
from_language: "fr",
|
||||
to_language: "uk",
|
||||
top_preferred_language: "en-US",
|
||||
top_preferred_language: "en",
|
||||
request_target: "select",
|
||||
auto_translate: false,
|
||||
},
|
||||
@@ -226,7 +226,7 @@ add_task(
|
||||
document_language: "es",
|
||||
from_language: "fa",
|
||||
to_language: "en",
|
||||
top_preferred_language: "en-US",
|
||||
top_preferred_language: "en",
|
||||
request_target: "select",
|
||||
auto_translate: false,
|
||||
},
|
||||
@@ -302,7 +302,7 @@ add_task(
|
||||
document_language: "es",
|
||||
from_language: "sl",
|
||||
to_language: "fi",
|
||||
top_preferred_language: "en-US",
|
||||
top_preferred_language: "en",
|
||||
request_target: "select",
|
||||
auto_translate: false,
|
||||
},
|
||||
|
||||
@@ -45,7 +45,7 @@ add_task(
|
||||
document_language: "es",
|
||||
from_language: "es",
|
||||
to_language: "en",
|
||||
top_preferred_language: "en-US",
|
||||
top_preferred_language: "en",
|
||||
text_source: "selection",
|
||||
},
|
||||
}
|
||||
@@ -65,7 +65,7 @@ add_task(
|
||||
document_language: "es",
|
||||
from_language: "es",
|
||||
to_language: "en",
|
||||
top_preferred_language: "en-US",
|
||||
top_preferred_language: "en",
|
||||
request_target: "select",
|
||||
auto_translate: false,
|
||||
source_text_code_units: 165,
|
||||
@@ -114,7 +114,7 @@ add_task(
|
||||
document_language: "es",
|
||||
from_language: "sl",
|
||||
to_language: "en",
|
||||
top_preferred_language: "en-US",
|
||||
top_preferred_language: "en",
|
||||
request_target: "select",
|
||||
auto_translate: false,
|
||||
},
|
||||
@@ -158,7 +158,7 @@ add_task(
|
||||
document_language: "es",
|
||||
from_language: "fa",
|
||||
to_language: "en",
|
||||
top_preferred_language: "en-US",
|
||||
top_preferred_language: "en",
|
||||
request_target: "select",
|
||||
auto_translate: false,
|
||||
},
|
||||
@@ -225,7 +225,7 @@ add_task(
|
||||
document_language: "es",
|
||||
from_language: "es",
|
||||
to_language: "en",
|
||||
top_preferred_language: "en-US",
|
||||
top_preferred_language: "en",
|
||||
text_source: "selection",
|
||||
},
|
||||
}
|
||||
@@ -245,7 +245,7 @@ add_task(
|
||||
document_language: "es",
|
||||
from_language: "es",
|
||||
to_language: "en",
|
||||
top_preferred_language: "en-US",
|
||||
top_preferred_language: "en",
|
||||
request_target: "select",
|
||||
auto_translate: false,
|
||||
source_text_code_units: 165,
|
||||
@@ -293,7 +293,7 @@ add_task(
|
||||
document_language: "es",
|
||||
from_language: "es",
|
||||
to_language: "fa",
|
||||
top_preferred_language: "en-US",
|
||||
top_preferred_language: "en",
|
||||
request_target: "select",
|
||||
auto_translate: false,
|
||||
source_text_code_units: 165,
|
||||
@@ -338,7 +338,7 @@ add_task(
|
||||
document_language: "es",
|
||||
from_language: "es",
|
||||
to_language: "uk",
|
||||
top_preferred_language: "en-US",
|
||||
top_preferred_language: "en",
|
||||
request_target: "select",
|
||||
auto_translate: false,
|
||||
source_text_code_units: 165,
|
||||
|
||||
@@ -30,7 +30,7 @@ add_task(
|
||||
document_language: "es",
|
||||
from_language: "es",
|
||||
to_language: "en",
|
||||
top_preferred_language: "en-US",
|
||||
top_preferred_language: "en",
|
||||
text_source: "selection",
|
||||
},
|
||||
}
|
||||
@@ -67,7 +67,7 @@ add_task(
|
||||
document_language: "es",
|
||||
from_language: "es",
|
||||
to_language: "en",
|
||||
top_preferred_language: "en-US",
|
||||
top_preferred_language: "en",
|
||||
text_source: "selection",
|
||||
},
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ add_task(
|
||||
document_language: "es",
|
||||
from_language: "es",
|
||||
to_language: "en",
|
||||
top_preferred_language: "en-US",
|
||||
top_preferred_language: "en",
|
||||
text_source: "selection",
|
||||
},
|
||||
}
|
||||
@@ -67,7 +67,7 @@ add_task(
|
||||
document_language: "es",
|
||||
from_language: "es",
|
||||
to_language: "en",
|
||||
top_preferred_language: "en-US",
|
||||
top_preferred_language: "en",
|
||||
text_source: "selection",
|
||||
},
|
||||
}
|
||||
@@ -87,7 +87,7 @@ add_task(
|
||||
document_language: "es",
|
||||
from_language: "es",
|
||||
to_language: "en",
|
||||
top_preferred_language: "en-US",
|
||||
top_preferred_language: "en",
|
||||
request_target: "select",
|
||||
auto_translate: false,
|
||||
source_text_code_units:
|
||||
|
||||
@@ -32,7 +32,7 @@ add_task(
|
||||
document_language: "es",
|
||||
from_language: "es",
|
||||
to_language: "en",
|
||||
top_preferred_language: "en-US",
|
||||
top_preferred_language: "en",
|
||||
text_source: "hyperlink",
|
||||
},
|
||||
}
|
||||
@@ -52,7 +52,7 @@ add_task(
|
||||
document_language: "es",
|
||||
from_language: "es",
|
||||
to_language: "en",
|
||||
top_preferred_language: "en-US",
|
||||
top_preferred_language: "en",
|
||||
request_target: "select",
|
||||
auto_translate: false,
|
||||
source_text_code_units: 23,
|
||||
|
||||
@@ -45,7 +45,7 @@ add_task(
|
||||
document_language: "es",
|
||||
from_language: "es",
|
||||
to_language: "en",
|
||||
top_preferred_language: "en-US",
|
||||
top_preferred_language: "en",
|
||||
text_source: "selection",
|
||||
},
|
||||
}
|
||||
@@ -65,7 +65,7 @@ add_task(
|
||||
document_language: "es",
|
||||
from_language: "es",
|
||||
to_language: "en",
|
||||
top_preferred_language: "en-US",
|
||||
top_preferred_language: "en",
|
||||
request_target: "select",
|
||||
auto_translate: false,
|
||||
source_text_code_units: 165,
|
||||
@@ -119,7 +119,7 @@ add_task(
|
||||
document_language: "es",
|
||||
from_language: "fi",
|
||||
to_language: "en",
|
||||
top_preferred_language: "en-US",
|
||||
top_preferred_language: "en",
|
||||
request_target: "select",
|
||||
auto_translate: false,
|
||||
source_text_code_units: 165,
|
||||
|
||||
@@ -31,7 +31,7 @@ add_task(
|
||||
document_language: "es",
|
||||
from_language: "fr",
|
||||
to_language: "en",
|
||||
top_preferred_language: "en-US",
|
||||
top_preferred_language: "en",
|
||||
text_source: "hyperlink",
|
||||
},
|
||||
}
|
||||
@@ -51,7 +51,7 @@ add_task(
|
||||
document_language: "es",
|
||||
from_language: "fr",
|
||||
to_language: "en",
|
||||
top_preferred_language: "en-US",
|
||||
top_preferred_language: "en",
|
||||
request_target: "select",
|
||||
auto_translate: false,
|
||||
source_text_code_units: 27,
|
||||
|
||||
@@ -33,7 +33,7 @@ add_task(
|
||||
document_language: "es",
|
||||
from_language: "fr",
|
||||
to_language: "en",
|
||||
top_preferred_language: "en-US",
|
||||
top_preferred_language: "en",
|
||||
text_source: "selection",
|
||||
},
|
||||
}
|
||||
@@ -53,7 +53,7 @@ add_task(
|
||||
document_language: "es",
|
||||
from_language: "fr",
|
||||
to_language: "en",
|
||||
top_preferred_language: "en-US",
|
||||
top_preferred_language: "en",
|
||||
request_target: "select",
|
||||
auto_translate: false,
|
||||
source_text_code_units:
|
||||
@@ -101,7 +101,7 @@ add_task(
|
||||
document_language: "es",
|
||||
from_language: "fr",
|
||||
to_language: "en",
|
||||
top_preferred_language: "en-US",
|
||||
top_preferred_language: "en",
|
||||
request_target: "select",
|
||||
auto_translate: false,
|
||||
source_text_code_units:
|
||||
|
||||
@@ -34,7 +34,7 @@ add_task(
|
||||
document_language: "es",
|
||||
from_language: "fr",
|
||||
to_language: "en",
|
||||
top_preferred_language: "en-US",
|
||||
top_preferred_language: "en",
|
||||
text_source: "selection",
|
||||
},
|
||||
}
|
||||
@@ -54,7 +54,7 @@ add_task(
|
||||
document_language: "es",
|
||||
from_language: "fr",
|
||||
to_language: "en",
|
||||
top_preferred_language: "en-US",
|
||||
top_preferred_language: "en",
|
||||
request_target: "select",
|
||||
auto_translate: false,
|
||||
source_text_code_units:
|
||||
@@ -101,7 +101,7 @@ add_task(
|
||||
document_language: "es",
|
||||
from_language: "fr",
|
||||
to_language: "en",
|
||||
top_preferred_language: "en-US",
|
||||
top_preferred_language: "en",
|
||||
request_target: "select",
|
||||
auto_translate: false,
|
||||
source_text_code_units:
|
||||
|
||||
@@ -28,7 +28,7 @@ add_task(
|
||||
document_language: "es",
|
||||
from_language: "es",
|
||||
to_language: "en",
|
||||
top_preferred_language: "en-US",
|
||||
top_preferred_language: "en",
|
||||
text_source: "hyperlink",
|
||||
},
|
||||
}
|
||||
@@ -48,7 +48,7 @@ add_task(
|
||||
document_language: "es",
|
||||
from_language: "es",
|
||||
to_language: "en",
|
||||
top_preferred_language: "en-US",
|
||||
top_preferred_language: "en",
|
||||
request_target: "select",
|
||||
auto_translate: false,
|
||||
source_text_code_units: 23,
|
||||
@@ -84,7 +84,7 @@ add_task(
|
||||
document_language: "es",
|
||||
from_language: "es",
|
||||
to_language: "fr",
|
||||
top_preferred_language: "en-US",
|
||||
top_preferred_language: "en",
|
||||
request_target: "select",
|
||||
auto_translate: false,
|
||||
source_text_code_units: 23,
|
||||
|
||||
@@ -27,7 +27,7 @@ add_task(
|
||||
document_language: "es",
|
||||
from_language: "es",
|
||||
to_language: "en",
|
||||
top_preferred_language: "en-US",
|
||||
top_preferred_language: "en",
|
||||
text_source: "hyperlink",
|
||||
},
|
||||
}
|
||||
@@ -47,7 +47,7 @@ add_task(
|
||||
document_language: "es",
|
||||
from_language: "es",
|
||||
to_language: "en",
|
||||
top_preferred_language: "en-US",
|
||||
top_preferred_language: "en",
|
||||
request_target: "select",
|
||||
auto_translate: false,
|
||||
source_text_code_units: 23,
|
||||
@@ -83,7 +83,7 @@ add_task(
|
||||
document_language: "es",
|
||||
from_language: "es",
|
||||
to_language: "fr",
|
||||
top_preferred_language: "en-US",
|
||||
top_preferred_language: "en",
|
||||
request_target: "select",
|
||||
auto_translate: false,
|
||||
source_text_code_units: 23,
|
||||
|
||||
@@ -34,7 +34,7 @@ add_task(
|
||||
document_language: "es",
|
||||
from_language: "es",
|
||||
to_language: "en",
|
||||
top_preferred_language: "en-US",
|
||||
top_preferred_language: "en",
|
||||
text_source: "selection",
|
||||
},
|
||||
}
|
||||
@@ -78,7 +78,7 @@ add_task(
|
||||
document_language: "es",
|
||||
from_language: "es",
|
||||
to_language: "en",
|
||||
top_preferred_language: "en-US",
|
||||
top_preferred_language: "en",
|
||||
text_source: "selection",
|
||||
},
|
||||
}
|
||||
@@ -127,7 +127,7 @@ add_task(
|
||||
document_language: "es",
|
||||
from_language: "fr",
|
||||
to_language: "en",
|
||||
top_preferred_language: "en-US",
|
||||
top_preferred_language: "en",
|
||||
request_target: "select",
|
||||
auto_translate: false,
|
||||
source_text_code_units:
|
||||
|
||||
@@ -163,15 +163,16 @@ function getByL10nId(l10nId, doc = document) {
|
||||
* @param {string} langTag - A BCP-47 language tag.
|
||||
*/
|
||||
const getIntlDisplayName = (() => {
|
||||
let languageDisplayNames = null;
|
||||
let displayNames = null;
|
||||
|
||||
return langTag => {
|
||||
if (!languageDisplayNames) {
|
||||
languageDisplayNames = TranslationsParent.createLanguageDisplayNames({
|
||||
if (!displayNames) {
|
||||
displayNames = new Services.intl.DisplayNames(undefined, {
|
||||
type: "language",
|
||||
fallback: "none",
|
||||
});
|
||||
}
|
||||
return languageDisplayNames.of(langTag);
|
||||
return displayNames.of(langTag);
|
||||
};
|
||||
})();
|
||||
|
||||
@@ -681,7 +682,7 @@ class FullPageTranslationsTestUtils {
|
||||
);
|
||||
is(
|
||||
locale.innerText,
|
||||
toLanguage.split("-")[0],
|
||||
toLanguage,
|
||||
`The expected language tag "${toLanguage}" is shown.`
|
||||
);
|
||||
is(
|
||||
@@ -1701,10 +1702,7 @@ class SelectTranslationsTestUtils {
|
||||
|
||||
await waitForCondition(
|
||||
() =>
|
||||
TranslationsUtils.langTagsMatch(
|
||||
menuItem.getAttribute("target-language"),
|
||||
expectedTargetLanguage
|
||||
),
|
||||
menuItem.getAttribute("target-language") === expectedTargetLanguage,
|
||||
`Waiting for translate-selection context menu item to match the expected target language ${expectedTargetLanguage}`
|
||||
);
|
||||
await waitForCondition(
|
||||
|
||||
@@ -7,9 +7,9 @@ translations.inference:
|
||||
fetch:
|
||||
artifact-name: bergamot-translator
|
||||
type: static-url
|
||||
url: https://firefox-settings-attachments.cdn.mozilla.net/main-workspace/translations-wasm/ec4aab08-4e7c-4a62-a7a5-ee6874a5d1a2.wasm
|
||||
sha256: e67e2f8be1a3fc0d9b00adce8b641cdf767bf3de90f1b3ccf732c2d711304fa3
|
||||
size: 4956176
|
||||
url: https://firefox-settings-attachments.cdn.mozilla.net/main-workspace/translations-wasm/95f4c7df-7cd2-4851-be11-6414679c1089.wasm
|
||||
sha256: 5430dd7f41709620b403e4628f357304c26120c9be634c732827c2ba9164d16c
|
||||
size: 4956240
|
||||
|
||||
translations.esen.lex:
|
||||
description: The Spanish to English translation lex artifact (version 1.0)
|
||||
|
||||
@@ -356,12 +356,13 @@ export class MLEngineParent extends JSWindowActorParent {
|
||||
*/
|
||||
static async #getWasmArrayRecord(client) {
|
||||
/** @type {WasmRecord[]} */
|
||||
const wasmRecords =
|
||||
await lazy.TranslationsParent.getMaxSupportedVersionRecords(client, {
|
||||
const wasmRecords = await lazy.TranslationsParent.getMaxVersionRecords(
|
||||
client,
|
||||
{
|
||||
filters: { name: MLEngineParent.WASM_FILENAME },
|
||||
minSupportedMajorVersion: MLEngineParent.WASM_MAJOR_VERSION,
|
||||
maxSupportedMajorVersion: MLEngineParent.WASM_MAJOR_VERSION,
|
||||
});
|
||||
majorVersion: MLEngineParent.WASM_MAJOR_VERSION,
|
||||
}
|
||||
);
|
||||
|
||||
if (wasmRecords.length === 0) {
|
||||
// The remote settings client provides an empty list of records when there is
|
||||
|
||||
@@ -1,77 +0,0 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/**
|
||||
* A set of global static utility functions that are useful throughout the
|
||||
* Translations ecosystem within the Firefox code base.
|
||||
*/
|
||||
export class TranslationsUtils {
|
||||
/**
|
||||
* Normalizes the language tag for comparison within the Translations ecosystem.
|
||||
*
|
||||
* Prefers to compare languages with a script tag if one is available, only resorting
|
||||
* to returning the language tag in isolation if a script tag could not be derived.
|
||||
*
|
||||
* @param {string} langTag - A BCP-47 language tag.
|
||||
* @returns {string} - A BCP-47 language tag normalized for Translations.
|
||||
*/
|
||||
static normalizeLangTagForTranslations(langTag) {
|
||||
let locale = new Intl.Locale(langTag);
|
||||
|
||||
if (!locale.script) {
|
||||
// Attempt to populate a script tag via likely subtags.
|
||||
locale = locale.maximize();
|
||||
}
|
||||
|
||||
if (locale.script) {
|
||||
// If the locale has a script, use it.
|
||||
return `${locale.language}-${locale.script}`;
|
||||
}
|
||||
|
||||
return locale.language;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares two BCP-47 language tags for Translations compatibility.
|
||||
*
|
||||
* If one language tag belongs to one of our models, and the other
|
||||
* language tag is determined to be a match, then it is determined
|
||||
* that the model is compatible to for translation with that language.
|
||||
*
|
||||
* @param {string} lhsLangTag - The left-hand-side language tag to compare.
|
||||
* @param {string} rhsLangTag - The right-hand-side language tag to compare.
|
||||
*
|
||||
* @returns {boolean}
|
||||
* `true` if the language tags match, either directly or after normalization.
|
||||
* `false` if either tag is invalid or empty, or if they do not match.
|
||||
*
|
||||
* @see https://datatracker.ietf.org/doc/html/rfc5646#appendix-A
|
||||
*/
|
||||
static langTagsMatch(lhsLangTag, rhsLangTag) {
|
||||
if (!lhsLangTag || !rhsLangTag) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (lhsLangTag === rhsLangTag) {
|
||||
// A simple direct match.
|
||||
return true;
|
||||
}
|
||||
|
||||
if (lhsLangTag.split("-")[0] !== rhsLangTag.split("-")[0]) {
|
||||
// The language components of the tags do not match so there is no need to normalize them and compare.
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
return (
|
||||
TranslationsUtils.normalizeLangTagForTranslations(lhsLangTag) ===
|
||||
TranslationsUtils.normalizeLangTagForTranslations(rhsLangTag)
|
||||
);
|
||||
} catch {
|
||||
// One of the locales is not valid, just continue on to return false.
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -58,8 +58,6 @@ ChromeUtils.defineESModuleGetters(lazy, {
|
||||
setTimeout: "resource://gre/modules/Timer.sys.mjs",
|
||||
TranslationsTelemetry:
|
||||
"chrome://global/content/translations/TranslationsTelemetry.sys.mjs",
|
||||
TranslationsUtils:
|
||||
"chrome://global/content/translations/TranslationsUtils.sys.mjs",
|
||||
EngineProcess: "chrome://global/content/ml/EngineProcess.sys.mjs",
|
||||
});
|
||||
|
||||
@@ -310,77 +308,9 @@ export class TranslationsParent extends JSWindowActorParent {
|
||||
*
|
||||
* Release docs:
|
||||
* https://firefox-source-docs.mozilla.org/toolkit/components/translations/resources/03_bergamot.html
|
||||
*
|
||||
* Release History:
|
||||
*
|
||||
* 1.x WASM Major Versions
|
||||
*
|
||||
* - Compatible with all 1.x Translation models.
|
||||
*
|
||||
* 2.x WASM Major Versions
|
||||
*
|
||||
* - Compatible with all 1.x Translation models.
|
||||
*
|
||||
* - Compatible with all 2.x Translation models.
|
||||
*
|
||||
* Notes: The 2.x WASM binary introduces segmentation changes that are necessary
|
||||
* to translate CJK languages.
|
||||
*/
|
||||
static BERGAMOT_MAJOR_VERSION = 2;
|
||||
|
||||
/**
|
||||
* The BERGAMOT_MAJOR_VERSION defined above has only a single value, because there will
|
||||
* only ever be one instance of the WASM binary that is downloaded for all translations.
|
||||
*
|
||||
* However, the current Bergamot WASM binary may be backward compatible with existing models.
|
||||
* As such, the models use a range of major versions that are compatible with the current
|
||||
* WASM binary and/or source code changes.
|
||||
*
|
||||
* By incrementing only the maximum major version, this allows us to introduce new model types
|
||||
* that are compatible only with the latest source code or WASM binary while continuing to utilize
|
||||
* old model types that are backward compatible with the changes.
|
||||
*
|
||||
* - Models with versions less than the new maximum major version:
|
||||
* - Available to past versions of Firefox.
|
||||
* - Available to the current version of Firefox.
|
||||
*
|
||||
* - Models with versions equal to the new maximum major version:
|
||||
* - Not available to past versions of Firefox.
|
||||
* - Available to the current version of Firefox.
|
||||
*
|
||||
* By incrementing both the minimum and maximum major versions to the same value, this allows us to
|
||||
* introduce a hard cutoff point at which prior models are no longer compatible with the current version
|
||||
* of Firefox.
|
||||
*
|
||||
* - Models with versions less than the new minimum and maximum major versions:
|
||||
* - Available to past versions of Firefox.
|
||||
* - Not available to current and future versions of Firefox.
|
||||
*
|
||||
* - Models with versions equal to the new minimum and maximum major versions:
|
||||
* - Not available to past versions of Firefox.
|
||||
* - Available to the current version of Firefox.
|
||||
*
|
||||
* Release History:
|
||||
*
|
||||
* 1.x Model Major Versions
|
||||
*
|
||||
* - Compatible with 1.x Bergamot WASM binaries.
|
||||
* - Compatible with 2.x Bergamot WASM binaries.
|
||||
*
|
||||
* Notes: 1.x models are referred to as "tiny" models, and are the models that were shipped with the original
|
||||
* release of Translations in Firefox.
|
||||
*
|
||||
* 2.x Model Major Versions
|
||||
*
|
||||
* - Compatible with 2.x Bergamot WASM binaries.
|
||||
*
|
||||
* Notes: 2.x models are defined by any of two characteristics. The first characteristic is any CJK language model.
|
||||
* Only the 2.x WASM binaries support the segmentation concerns needed to interop with CJK language models.
|
||||
* The second characteristic is any "base" language model, which is larger than the "tiny" 1.x models.
|
||||
* Compatibility for base models is dependent on the code changes in Bug 1926100.
|
||||
*/
|
||||
static LANGUAGE_MODEL_MAJOR_VERSION_MIN = 1;
|
||||
static LANGUAGE_MODEL_MAJOR_VERSION_MAX = 2;
|
||||
static LANGUAGE_MODEL_MAJOR_VERSION = 1;
|
||||
|
||||
/**
|
||||
* Contains the state that would affect UI. Anytime this state is changed, a dispatch
|
||||
@@ -878,7 +808,7 @@ export class TranslationsParent extends JSWindowActorParent {
|
||||
try {
|
||||
// Wrap this in a try statement since users can manually edit this pref.
|
||||
TranslationsParent.#webContentLanguages.add(
|
||||
new Intl.Locale(locale).baseName
|
||||
new Intl.Locale(locale).language
|
||||
);
|
||||
} catch {
|
||||
// The locale was invalid, discard it.
|
||||
@@ -893,14 +823,13 @@ export class TranslationsParent extends JSWindowActorParent {
|
||||
// The user hasn't customized their accept languages, this means that English
|
||||
// is always provided as a fallback language, even if it is not available.
|
||||
TranslationsParent.#webContentLanguages.delete("en");
|
||||
TranslationsParent.#webContentLanguages.delete("en-US");
|
||||
}
|
||||
|
||||
if (TranslationsParent.#webContentLanguages.size === 0) {
|
||||
// The user has removed all of their web content languages, default to the
|
||||
// app locale.
|
||||
TranslationsParent.#webContentLanguages.add(
|
||||
new Intl.Locale(Services.locale.appLocaleAsBCP47).baseName
|
||||
new Intl.Locale(Services.locale.appLocaleAsBCP47).language
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -971,7 +900,7 @@ export class TranslationsParent extends JSWindowActorParent {
|
||||
const userSettingsLangTags = new Set();
|
||||
for (const locale of userSettingsLocales) {
|
||||
try {
|
||||
userSettingsLangTags.add(new Intl.Locale(locale).baseName);
|
||||
userSettingsLangTags.add(new Intl.Locale(locale).language);
|
||||
} catch (_) {
|
||||
// The locale was invalid, discard it.
|
||||
}
|
||||
@@ -998,10 +927,7 @@ export class TranslationsParent extends JSWindowActorParent {
|
||||
static getPreferredLanguages({ excludeLangTags } = {}) {
|
||||
if (TranslationsParent.#preferredLanguages) {
|
||||
return TranslationsParent.#preferredLanguages.filter(
|
||||
langTag =>
|
||||
!excludeLangTags?.some(langTagToExclude =>
|
||||
lazy.TranslationsUtils.langTagsMatch(langTagToExclude, langTag)
|
||||
)
|
||||
langTag => !excludeLangTags?.includes(langTag)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1034,10 +960,7 @@ export class TranslationsParent extends JSWindowActorParent {
|
||||
TranslationsParent.#preferredLanguages = [...preferredLanguages];
|
||||
|
||||
return TranslationsParent.#preferredLanguages.filter(
|
||||
langTag =>
|
||||
!excludeLangTags?.some(langTagToExclude =>
|
||||
lazy.TranslationsUtils.langTagsMatch(langTagToExclude, langTag)
|
||||
)
|
||||
langTag => !excludeLangTags?.includes(langTag)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1330,15 +1253,16 @@ export class TranslationsParent extends JSWindowActorParent {
|
||||
/** @type {Map<string, string>} */
|
||||
const displayNames = new Map();
|
||||
{
|
||||
const languageDisplayNames =
|
||||
TranslationsParent.createLanguageDisplayNames();
|
||||
const dn = new Services.intl.DisplayNames(undefined, {
|
||||
type: "language",
|
||||
});
|
||||
|
||||
for (const langTagSet of [fromLanguages, toLanguages]) {
|
||||
for (const langTag of langTagSet.keys()) {
|
||||
if (displayNames.has(langTag)) {
|
||||
continue;
|
||||
}
|
||||
displayNames.set(langTag, languageDisplayNames.of(langTag));
|
||||
displayNames.set(langTag, dn.of(langTag));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1378,13 +1302,10 @@ export class TranslationsParent extends JSWindowActorParent {
|
||||
}
|
||||
}
|
||||
|
||||
const appLangTag = Services.locale.appLocaleAsBCP47;
|
||||
for (const langTag of displayNames.keys()) {
|
||||
if (lazy.TranslationsUtils.langTagsMatch(langTag, appLangTag)) {
|
||||
displayNames.delete(langTag);
|
||||
break;
|
||||
}
|
||||
}
|
||||
let appLangTag = new Intl.Locale(Services.locale.appLocaleAsBCP47).language;
|
||||
|
||||
// Don't offer to download the app's language.
|
||||
displayNames.delete(appLangTag);
|
||||
|
||||
// Sort the list of languages by the display names.
|
||||
return [...displayNames.entries()]
|
||||
@@ -1396,34 +1317,18 @@ export class TranslationsParent extends JSWindowActorParent {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates and retrieves an `Intl.DisplayNames` object for displaying languages
|
||||
* in translation-related user interfaces across the browser.
|
||||
* Get the display name for the given language Tag.
|
||||
*
|
||||
* @param {Record<string, string>} [options={}]
|
||||
* - Optional parameters to customize the display of language names.
|
||||
* @param {string} [options.fallback="code"]
|
||||
* - Determines the behavior when a language display name is unavailable:
|
||||
* "code": Fallback to the language code.
|
||||
* "none": No fallback; return `undefined`.
|
||||
* @param {string} [options.languageDisplay="standard"]
|
||||
* - Specifies how to display the language names:
|
||||
* "standard": Display the standard form of the language name e.g. "Chinese (Simplified)"
|
||||
* "dialect": Display the dialect form if available e.g. "Simplified Chinese"
|
||||
*
|
||||
* @returns {Intl.DisplayNames}
|
||||
* An `Intl.DisplayNames` object configured to format language names according to the given options.
|
||||
*
|
||||
* @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DisplayNames
|
||||
* @param {string} langTag
|
||||
* @returns {string}
|
||||
*/
|
||||
static createLanguageDisplayNames({
|
||||
fallback = "code",
|
||||
languageDisplay = "standard",
|
||||
} = {}) {
|
||||
return new Services.intl.DisplayNames(undefined, {
|
||||
type: "language",
|
||||
languageDisplay,
|
||||
fallback,
|
||||
});
|
||||
static getLanguageDisplayName(langTag) {
|
||||
// Services.intl.getLanguageDisplayNames takes a list of language codes and
|
||||
// returns a list of correspoding display names. Hence the langTag is sent as a list
|
||||
let displayName = Services.intl.getLanguageDisplayNames(undefined, [
|
||||
langTag,
|
||||
]);
|
||||
return displayName[0];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1651,7 +1556,7 @@ export class TranslationsParent extends JSWindowActorParent {
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the maximum compatible major version of each record in the RemoteSettingsClient.
|
||||
* Retrieves the maximum major version of each record in the RemoteSettingsClient.
|
||||
*
|
||||
* If the client contains two different-version copies of the same record (e.g. 1.0 and 1.1)
|
||||
* then only the 1.1-version record will be returned in the resulting collection.
|
||||
@@ -1663,10 +1568,7 @@ export class TranslationsParent extends JSWindowActorParent {
|
||||
* Filters should correspond to properties on the RemoteSettings records themselves.
|
||||
* For example, A filter to retrieve only records with a `fromLang` value of "en" and a `toLang` value of "es":
|
||||
* { filters: { fromLang: "en", toLang: "es" } }
|
||||
* @param {number} options.minSupportedMajorVersion
|
||||
* The minimum major record version that is supported in this build of Firefox.
|
||||
* @param {number} options.maxSupportedMajorVersion
|
||||
* The maximum major record version that is supported in this build of Firefox.
|
||||
* @param {number} options.majorVersion
|
||||
* @param {Function} [options.lookupKey=(record => record.name)]
|
||||
* The function to use to extract a lookup key from each record.
|
||||
* This function should take a record as input and return a string that represents the lookup key for the record.
|
||||
@@ -1674,19 +1576,12 @@ export class TranslationsParent extends JSWindowActorParent {
|
||||
* non-unique name values, it may be necessary to provide an alternative function here.
|
||||
* @returns {Array<TranslationModelRecord | WasmRecord>}
|
||||
*/
|
||||
static async getMaxSupportedVersionRecords(
|
||||
static async getMaxVersionRecords(
|
||||
remoteSettingsClient,
|
||||
{
|
||||
filters = {},
|
||||
minSupportedMajorVersion,
|
||||
maxSupportedMajorVersion,
|
||||
lookupKey = record => record.name,
|
||||
} = {}
|
||||
{ filters = {}, majorVersion, lookupKey = record => record.name } = {}
|
||||
) {
|
||||
if (!minSupportedMajorVersion || !maxSupportedMajorVersion) {
|
||||
throw new Error(
|
||||
"A minimum and maximum major version must be specified to retrieve records."
|
||||
);
|
||||
if (!majorVersion) {
|
||||
throw new Error("Expected the records to have a major version.");
|
||||
}
|
||||
try {
|
||||
await chaosMode(1 / 4);
|
||||
@@ -1728,8 +1623,7 @@ export class TranslationsParent extends JSWindowActorParent {
|
||||
}
|
||||
if (
|
||||
TranslationsParent.isBetterRecordVersion(
|
||||
minSupportedMajorVersion,
|
||||
maxSupportedMajorVersion,
|
||||
majorVersion,
|
||||
record.version,
|
||||
existing?.version
|
||||
)
|
||||
@@ -1742,36 +1636,20 @@ export class TranslationsParent extends JSWindowActorParent {
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the contending record version is a better record version than the current best record version.
|
||||
* Applies the constraint of matching for the best matching major version.
|
||||
*
|
||||
* For the contending version to be considered better, it must fall within the supported-version range and be
|
||||
* a larger version than the current best version (if a current best version is provided).
|
||||
*
|
||||
* @param {number} minSupportedMajorVersion - The minimum major record version that is supported in this build of Firefox.
|
||||
* @param {number} maxSupportedMajorVersion - The maximum major record version that is supported in this build of Firefox.
|
||||
* @param {string} contendingVersion - The version of the contending record that is actively being evaluated.
|
||||
* @param {string} [currentBestVersion] - The version of a previously encountered record that is currently best.
|
||||
* @param {number} majorVersion
|
||||
* @param {string} nextVersion
|
||||
* @param {string} [existingVersion]
|
||||
*/
|
||||
static isBetterRecordVersion(
|
||||
minSupportedMajorVersion,
|
||||
maxSupportedMajorVersion,
|
||||
contendingVersion,
|
||||
currentBestVersion
|
||||
) {
|
||||
static isBetterRecordVersion(majorVersion, nextVersion, existingVersion) {
|
||||
return (
|
||||
// Check that the contending version is within range of the minimum major version.
|
||||
Services.vc.compare(
|
||||
`${minSupportedMajorVersion}.0a`,
|
||||
contendingVersion
|
||||
) <= 0 &&
|
||||
// Check that the contending version is within range of the maximum major version.
|
||||
Services.vc.compare(
|
||||
`${maxSupportedMajorVersion + 1}.0a`,
|
||||
contendingVersion
|
||||
) > 0 &&
|
||||
// Check that the new record greater than the current best version.
|
||||
(!currentBestVersion ||
|
||||
Services.vc.compare(currentBestVersion, contendingVersion) < 0)
|
||||
// Check that this is a major version record we can support.
|
||||
Services.vc.compare(`${majorVersion}.0a`, nextVersion) <= 0 &&
|
||||
Services.vc.compare(`${majorVersion + 1}.0a`, nextVersion) > 0 &&
|
||||
// Check that the new record is bigger version number
|
||||
(!existingVersion ||
|
||||
Services.vc.compare(existingVersion, nextVersion) < 0)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1795,11 +1673,8 @@ export class TranslationsParent extends JSWindowActorParent {
|
||||
|
||||
/** @type {TranslationModelRecord[]} */
|
||||
const translationModelRecords =
|
||||
await TranslationsParent.getMaxSupportedVersionRecords(client, {
|
||||
minSupportedMajorVersion:
|
||||
TranslationsParent.LANGUAGE_MODEL_MAJOR_VERSION_MIN,
|
||||
maxSupportedMajorVersion:
|
||||
TranslationsParent.LANGUAGE_MODEL_MAJOR_VERSION_MAX,
|
||||
await TranslationsParent.getMaxVersionRecords(client, {
|
||||
majorVersion: TranslationsParent.LANGUAGE_MODEL_MAJOR_VERSION,
|
||||
// Names in this collection are not unique, so we are appending the languagePairKey
|
||||
// to guarantee uniqueness.
|
||||
lookupKey: record =>
|
||||
@@ -1997,12 +1872,13 @@ export class TranslationsParent extends JSWindowActorParent {
|
||||
lazy.console.log(`Getting remote bergamot-translator wasm records.`);
|
||||
|
||||
/** @type {WasmRecord[]} */
|
||||
const wasmRecords =
|
||||
await TranslationsParent.getMaxSupportedVersionRecords(client, {
|
||||
const wasmRecords = await TranslationsParent.getMaxVersionRecords(
|
||||
client,
|
||||
{
|
||||
filters: { name: "bergamot-translator" },
|
||||
minSupportedMajorVersion: TranslationsParent.BERGAMOT_MAJOR_VERSION,
|
||||
maxSupportedMajorVersion: TranslationsParent.BERGAMOT_MAJOR_VERSION,
|
||||
});
|
||||
majorVersion: TranslationsParent.BERGAMOT_MAJOR_VERSION,
|
||||
}
|
||||
);
|
||||
|
||||
if (wasmRecords.length === 0) {
|
||||
// The remote settings client provides an empty list of records when there is
|
||||
@@ -2090,9 +1966,8 @@ export class TranslationsParent extends JSWindowActorParent {
|
||||
* @param {string} language The BCP 47 language tag.
|
||||
*/
|
||||
static async deleteLanguageFiles(language) {
|
||||
const appLanguage = lazy.TranslationsUtils.normalizeLangTagForTranslations(
|
||||
Services.locale.appLocaleAsBCP47
|
||||
);
|
||||
const appLanguage = new Intl.Locale(Services.locale.appLocaleAsBCP47)
|
||||
.language;
|
||||
return TranslationsParent.deleteLanguageFilesToAndFromPair(
|
||||
language,
|
||||
appLanguage,
|
||||
@@ -2306,7 +2181,7 @@ export class TranslationsParent extends JSWindowActorParent {
|
||||
|
||||
let matchedRecords = new Set();
|
||||
|
||||
if (lazy.TranslationsUtils.langTagsMatch(languageA, languageB)) {
|
||||
if (languageA === languageB) {
|
||||
// There are no records if the requested language and app language are the same.
|
||||
return matchedRecords;
|
||||
}
|
||||
@@ -2314,10 +2189,7 @@ export class TranslationsParent extends JSWindowActorParent {
|
||||
const addLanguagePair = (fromLang, toLang) => {
|
||||
let matchFound = false;
|
||||
for (const record of records.values()) {
|
||||
if (
|
||||
lazy.TranslationsUtils.langTagsMatch(record.fromLang, fromLang) &&
|
||||
lazy.TranslationsUtils.langTagsMatch(record.toLang, toLang)
|
||||
) {
|
||||
if (record.fromLang === fromLang && record.toLang === toLang) {
|
||||
matchedRecords.add(record);
|
||||
matchFound = true;
|
||||
}
|
||||
@@ -2371,9 +2243,8 @@ export class TranslationsParent extends JSWindowActorParent {
|
||||
requestedLanguage,
|
||||
includePivotRecords
|
||||
) {
|
||||
const appLanguage = lazy.TranslationsUtils.normalizeLangTagForTranslations(
|
||||
Services.locale.appLocaleAsBCP47
|
||||
);
|
||||
const appLanguage = new Intl.Locale(Services.locale.appLocaleAsBCP47)
|
||||
.language;
|
||||
|
||||
return TranslationsParent.getRecordsForTranslatingToAndFromPair(
|
||||
requestedLanguage,
|
||||
@@ -2852,77 +2723,33 @@ export class TranslationsParent extends JSWindowActorParent {
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds a compatible source language tag for translation synchronously.
|
||||
* Searches the provided language pairs for a match based on the given language tag.
|
||||
* Checks if a given language tag is supported for translation
|
||||
* when translating from this language into other languages.
|
||||
*
|
||||
* @param {string} langTag - A BCP-47 language tag to match against source languages.
|
||||
* @param {Array<{ fromLang: string, toLang: string }>} languagePairs - An array of language pair objects,
|
||||
* where each object contains `fromLang` and `toLang` properties.
|
||||
* @returns {string | null} - The compatible source language tag, or `null` if no match is found.
|
||||
* @param {string} langTag - A BCP-47 language tag.
|
||||
* @returns {Promise<boolean>}
|
||||
*/
|
||||
static findCompatibleSourceLangTagSync(langTag, languagePairs) {
|
||||
static async isSupportedAsFromLang(langTag) {
|
||||
if (!langTag) {
|
||||
return null;
|
||||
return false;
|
||||
}
|
||||
|
||||
const langPair = languagePairs.find(({ fromLang }) =>
|
||||
lazy.TranslationsUtils.langTagsMatch(fromLang, langTag)
|
||||
);
|
||||
|
||||
return langPair?.fromLang;
|
||||
let languagePairs = await TranslationsParent.getLanguagePairs();
|
||||
return Boolean(languagePairs.find(({ fromLang }) => fromLang === langTag));
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds a compatible source language tag for translation.
|
||||
* Fetches language pairs and then determines a match for the given language tag.
|
||||
* Checks if a given language tag is supported for translation
|
||||
* when translating from other languages into this language.
|
||||
*
|
||||
* @param {string} langTag - A BCP-47 language tag to match against source languages.
|
||||
* @returns {Promise<string | null>} - A promise resolving to the compatible source language tag,
|
||||
* or `null` if no match is found.
|
||||
* @param {string} langTag - A BCP-47 language tag.
|
||||
* @returns {Promise<boolean>}
|
||||
*/
|
||||
static async findCompatibleSourceLangTag(langTag) {
|
||||
const languagePairs = await TranslationsParent.getLanguagePairs();
|
||||
return TranslationsParent.findCompatibleSourceLangTagSync(
|
||||
langTag,
|
||||
languagePairs
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds a compatible target language tag for translation synchronously.
|
||||
* Searches the provided language pairs for a match based on the given language tag.
|
||||
*
|
||||
* @param {string} langTag - A BCP-47 language tag to match against target languages.
|
||||
* @param {Array<{ fromLang: string, toLang: string }>} languagePairs - An array of language pair objects,
|
||||
* where each object contains `fromLang` and `toLang` properties.
|
||||
* @returns {string | null} - The compatible target language tag, or `null` if no match is found.
|
||||
*/
|
||||
static findCompatibleTargetLangTagSync(langTag, languagePairs) {
|
||||
static async isSupportedAsToLang(langTag) {
|
||||
if (!langTag) {
|
||||
return null;
|
||||
return false;
|
||||
}
|
||||
|
||||
const langPair = languagePairs.find(({ toLang }) =>
|
||||
lazy.TranslationsUtils.langTagsMatch(toLang, langTag)
|
||||
);
|
||||
|
||||
return langPair?.toLang;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds a compatible target language tag for translation.
|
||||
* Fetches language pairs and then determines a match for the given language tag.
|
||||
*
|
||||
* @param {string} langTag - A BCP-47 language tag to match against target languages.
|
||||
* @returns {Promise<string | null>} - A promise resolving to the compatible target language tag,
|
||||
* or `null` if no match is found.
|
||||
*/
|
||||
static async findCompatibleTargetLangTag(langTag) {
|
||||
const languagePairs = await TranslationsParent.getLanguagePairs();
|
||||
return TranslationsParent.findCompatibleTargetLangTagSync(
|
||||
langTag,
|
||||
languagePairs
|
||||
);
|
||||
let languagePairs = await TranslationsParent.getLanguagePairs();
|
||||
return Boolean(languagePairs.find(({ toLang }) => toLang === langTag));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2937,44 +2764,15 @@ export class TranslationsParent extends JSWindowActorParent {
|
||||
excludeLangTags,
|
||||
});
|
||||
|
||||
const languagePairs = await TranslationsParent.getLanguagePairs();
|
||||
for (const langTag of preferredLanguages) {
|
||||
const compatibleLangTag =
|
||||
TranslationsParent.findCompatibleTargetLangTagSync(
|
||||
langTag,
|
||||
languagePairs
|
||||
);
|
||||
if (compatibleLangTag) {
|
||||
return compatibleLangTag;
|
||||
if (await TranslationsParent.isSupportedAsToLang(langTag)) {
|
||||
return langTag;
|
||||
}
|
||||
}
|
||||
|
||||
return PIVOT_LANGUAGE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to make the language tag more specific if it is a supported macro language tag.
|
||||
* If no special cases apply, the provided language tag is returned as-is.
|
||||
*
|
||||
* @param {string} langTag - A BCP-47 language tag to evaluate and possibly refine.
|
||||
* @returns {Promise<string>} - The refined language tag, or null if processing was interrupted.
|
||||
*/
|
||||
maybeRefineMacroLanguageTag(langTag) {
|
||||
if (langTag === "no") {
|
||||
// Choose "Norwegian Bokmål" over "Norwegian Nynorsk" as it is more widely used.
|
||||
//
|
||||
// https://en.wikipedia.org/wiki/Norwegian_language#Bokm%C3%A5l_and_Nynorsk
|
||||
//
|
||||
// > A 2005 poll indicates that 86.3% use primarily Bokmål as their daily
|
||||
// > written language, 5.5% use both Bokmål and Nynorsk, and 7.5% use
|
||||
// > primarily Nynorsk.
|
||||
return "nb";
|
||||
}
|
||||
|
||||
// No special cases were handled above, so pass the langTag through.
|
||||
return langTag;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the lang tags that should be offered for translation. This is in the parent
|
||||
* rather than the child to remove the per-content process memory allocation amount.
|
||||
@@ -2988,7 +2786,11 @@ export class TranslationsParent extends JSWindowActorParent {
|
||||
if (this.languageState.detectedLanguages) {
|
||||
return this.languageState.detectedLanguages;
|
||||
}
|
||||
|
||||
const langTags = {
|
||||
docLangTag: null,
|
||||
userLangTag: null,
|
||||
isDocLangTagSupported: false,
|
||||
};
|
||||
if (!TranslationsParent.getIsTranslationsEngineSupported()) {
|
||||
return null;
|
||||
}
|
||||
@@ -3000,71 +2802,53 @@ export class TranslationsParent extends JSWindowActorParent {
|
||||
}
|
||||
}
|
||||
|
||||
documentElementLang = this.maybeRefineMacroLanguageTag(documentElementLang);
|
||||
|
||||
let languagePairs = await TranslationsParent.getLanguagePairs();
|
||||
if (this.#isDestroyed) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const langTags = {
|
||||
docLangTag: null,
|
||||
userLangTag: null,
|
||||
isDocLangTagSupported: false,
|
||||
};
|
||||
|
||||
/**
|
||||
* Attempts to find a compatible source language tag that matches
|
||||
* langTags.docLangTag. If a match is found, sets langTags.docLangTag
|
||||
* to the normalized value and sets langTags.isDocLangTagSupported to true.
|
||||
*/
|
||||
function findCompatibleDocLangTag() {
|
||||
const compatibleLangTag =
|
||||
TranslationsParent.findCompatibleSourceLangTagSync(
|
||||
langTags.docLangTag,
|
||||
languagePairs
|
||||
);
|
||||
|
||||
if (compatibleLangTag) {
|
||||
langTags.docLangTag = compatibleLangTag;
|
||||
langTags.isDocLangTagSupported = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to normalize the langTags.docLangTag value to a language tag that is
|
||||
* compatible as a source language for one of the translation models. If a language
|
||||
* tag is found, sets langTags.isDocLangTagSupported to `true`.
|
||||
*/
|
||||
function maybeNormalizeDocLangTag() {
|
||||
if (!langTags.isDocLangTagSupported) {
|
||||
findCompatibleDocLangTag();
|
||||
}
|
||||
|
||||
if (langTags.docLangTag && !langTags.isDocLangTagSupported) {
|
||||
// We have found a docLangTag, but it is still not supported.
|
||||
// Try it again with a canonicalized version.
|
||||
langTags.docLangTag = Intl.getCanonicalLocales(langTags.docLangTag)[0];
|
||||
findCompatibleDocLangTag();
|
||||
}
|
||||
}
|
||||
const determineIsDocLangTagSupported = () =>
|
||||
Boolean(
|
||||
languagePairs.find(({ fromLang }) => fromLang === langTags.docLangTag)
|
||||
);
|
||||
|
||||
// First try to get the langTag from the document's markup.
|
||||
// Attempt to find a supported locale from highest specificity to lowest specificity.
|
||||
try {
|
||||
langTags.docLangTag = new Intl.Locale(documentElementLang).baseName;
|
||||
maybeNormalizeDocLangTag();
|
||||
} catch (error) {
|
||||
// Failed to create a locale from documentElementLang, continue on.
|
||||
}
|
||||
const docLocale = new Intl.Locale(documentElementLang);
|
||||
langTags.docLangTag = docLocale.language;
|
||||
langTags.isDocLangTagSupported = determineIsDocLangTagSupported();
|
||||
} catch (error) {}
|
||||
|
||||
if (!langTags.docLangTag) {
|
||||
if (langTags.docLangTag) {
|
||||
// If it's not supported, try it again with a canonicalized version.
|
||||
if (!langTags.isDocLangTagSupported) {
|
||||
langTags.docLangTag = Intl.getCanonicalLocales(langTags.docLangTag)[0];
|
||||
langTags.isDocLangTagSupported = determineIsDocLangTagSupported();
|
||||
}
|
||||
|
||||
// If it's still not supported, map macro language codes to specific ones.
|
||||
// https://en.wikipedia.org/wiki/ISO_639_macrolanguage
|
||||
if (!langTags.isDocLangTagSupported) {
|
||||
// If more macro language codes are needed, this logic can be expanded.
|
||||
if (langTags.docLangTag === "no") {
|
||||
// Choose "Norwegian Bokmål" over "Norwegian Nynorsk" as it is more widely used.
|
||||
//
|
||||
// https://en.wikipedia.org/wiki/Norwegian_language#Bokm%C3%A5l_and_Nynorsk
|
||||
//
|
||||
// > A 2005 poll indicates that 86.3% use primarily Bokmål as their daily
|
||||
// > written language, 5.5% use both Bokmål and Nynorsk, and 7.5% use
|
||||
// > primarily Nynorsk.
|
||||
langTags.docLangTag = "nb";
|
||||
langTags.isDocLangTagSupported = determineIsDocLangTagSupported();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// If the document's markup had no specified langTag, attempt to identify the page's language.
|
||||
langTags.docLangTag = await this.queryIdentifyLanguage();
|
||||
if (this.#isDestroyed) {
|
||||
return null;
|
||||
}
|
||||
maybeNormalizeDocLangTag();
|
||||
langTags.isDocLangTagSupported = determineIsDocLangTagSupported();
|
||||
}
|
||||
|
||||
if (!langTags.docLangTag) {
|
||||
@@ -3088,13 +2872,7 @@ export class TranslationsParent extends JSWindowActorParent {
|
||||
return langTags;
|
||||
}
|
||||
|
||||
if (
|
||||
TranslationsParent.getWebContentLanguages()
|
||||
.keys()
|
||||
.some(langTag =>
|
||||
lazy.TranslationsUtils.langTagsMatch(langTag, langTags.docLangTag)
|
||||
)
|
||||
) {
|
||||
if (TranslationsParent.getWebContentLanguages().has(langTags.docLangTag)) {
|
||||
// The doc language has been marked as a known language by the user, do not
|
||||
// offer a translation.
|
||||
const message =
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
function loadBergamot(Module) {
|
||||
var BERGAMOT_VERSION_FULL = "v0.5.0+b475d25";
|
||||
var BERGAMOT_VERSION_FULL = "v0.5.0+f901047";
|
||||
null;
|
||||
|
||||
var Module = typeof Module != "undefined" ? Module : {};
|
||||
|
||||
@@ -24,7 +24,7 @@ origin:
|
||||
|
||||
# Revision to pull in
|
||||
# Must be a long or short commit SHA (long preferred)
|
||||
revision: b475d25cb4568dd7bf37f80b8804030f1820bd4b
|
||||
revision: f9010478a45cd40bf7ad3d0aecdd62dd281ec5d6
|
||||
|
||||
# The package's license, where possible using the mnemonic from
|
||||
# https://spdx.org/licenses/
|
||||
|
||||
@@ -7,8 +7,6 @@ const lazy = {};
|
||||
ChromeUtils.defineESModuleGetters(lazy, {
|
||||
setTimeout: "resource://gre/modules/Timer.sys.mjs",
|
||||
clearTimeout: "resource://gre/modules/Timer.sys.mjs",
|
||||
TranslationsUtils:
|
||||
"chrome://global/content/translations/TranslationsUtils.sys.mjs",
|
||||
});
|
||||
|
||||
ChromeUtils.defineLazyGetter(lazy, "console", () => {
|
||||
@@ -525,6 +523,18 @@ export class TranslationsDocument {
|
||||
* @type {string}
|
||||
*/
|
||||
this.documentLanguage = documentLanguage;
|
||||
if (documentLanguage.length !== 2) {
|
||||
throw new Error(
|
||||
"Expected the document language to be a valid 2 letter BCP 47 language tag: " +
|
||||
documentLanguage
|
||||
);
|
||||
}
|
||||
if (toLanguage.length !== 2) {
|
||||
throw new Error(
|
||||
"Expected the destination language to be a valid 2 letter BCP 47 language tag: " +
|
||||
toLanguage
|
||||
);
|
||||
}
|
||||
|
||||
/** @type {QueuedTranslator} */
|
||||
this.translator = new QueuedTranslator(
|
||||
@@ -1834,9 +1844,7 @@ export class TranslationsDocument {
|
||||
}
|
||||
|
||||
// First, cheaply check if language tags match, without canonicalizing.
|
||||
if (
|
||||
lazy.TranslationsUtils.langTagsMatch(this.documentLanguage, node.lang)
|
||||
) {
|
||||
if (langTagsMatch(this.documentLanguage, node.lang)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1845,10 +1853,7 @@ export class TranslationsDocument {
|
||||
// throws, so don't trust that the language tags are formatting correctly.
|
||||
const [language] = Intl.getCanonicalLocales(node.lang);
|
||||
|
||||
return lazy.TranslationsUtils.langTagsMatch(
|
||||
this.documentLanguage,
|
||||
language
|
||||
);
|
||||
return langTagsMatch(this.documentLanguage, language);
|
||||
} catch (_error) {
|
||||
return false;
|
||||
}
|
||||
@@ -1873,6 +1878,28 @@ function isNodeHidden(node) {
|
||||
return style.display === "none" || style.visibility === "hidden";
|
||||
}
|
||||
|
||||
/**
|
||||
* This function cheaply checks that language tags match.
|
||||
*
|
||||
* @param {string} knownLanguage
|
||||
* @param {string} otherLanguage
|
||||
*/
|
||||
function langTagsMatch(knownLanguage, otherLanguage) {
|
||||
if (knownLanguage === otherLanguage) {
|
||||
// A simple direct match.
|
||||
return true;
|
||||
}
|
||||
if (knownLanguage.length !== 2) {
|
||||
throw new Error("Expected the knownLanguage to be of length 2.");
|
||||
}
|
||||
// Check if the language tags part match, e.g. "en" and "en-US".
|
||||
return (
|
||||
knownLanguage[0] === otherLanguage[0] &&
|
||||
knownLanguage[1] === otherLanguage[1] &&
|
||||
otherLanguage[2] === "-"
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function returns the correct element to determine the
|
||||
* style of node.
|
||||
|
||||
@@ -13,7 +13,6 @@ toolkit.jar:
|
||||
content/global/translations/translations.mjs (content/translations.mjs)
|
||||
content/global/translations/Translator.mjs (content/Translator.mjs)
|
||||
content/global/translations/TranslationsTelemetry.sys.mjs (TranslationsTelemetry.sys.mjs)
|
||||
content/global/translations/TranslationsUtils.sys.mjs (TranslationsUtils.sys.mjs)
|
||||
content/global/translations/icons/swap-languages.svg (content/icons/swap-languages.svg)
|
||||
|
||||
# Uncomment this line to test a local build of Bergamot. It will automatically be loaded in.
|
||||
|
||||
@@ -95,23 +95,23 @@ add_task(async function test_language_support_checks() {
|
||||
const { languagePairs } = await TranslationsParent.getSupportedLanguages();
|
||||
for (const { fromLang, toLang } of languagePairs) {
|
||||
ok(
|
||||
await TranslationsParent.findCompatibleSourceLangTag(fromLang),
|
||||
await TranslationsParent.isSupportedAsFromLang(fromLang),
|
||||
"Each from-language should be supported as a translation source language."
|
||||
);
|
||||
|
||||
ok(
|
||||
await TranslationsParent.findCompatibleTargetLangTag(toLang),
|
||||
await TranslationsParent.isSupportedAsToLang(toLang),
|
||||
"Each to-language should be supported as a translation target language."
|
||||
);
|
||||
|
||||
is(
|
||||
Boolean(await TranslationsParent.findCompatibleTargetLangTag(fromLang)),
|
||||
await TranslationsParent.isSupportedAsToLang(fromLang),
|
||||
languagePairs.some(({ toLang }) => toLang === fromLang),
|
||||
"A from-language should be supported as a to-language if it also exists in the to-language list."
|
||||
);
|
||||
|
||||
is(
|
||||
Boolean(await TranslationsParent.findCompatibleSourceLangTag(toLang)),
|
||||
await TranslationsParent.isSupportedAsFromLang(toLang),
|
||||
languagePairs.some(({ fromLang }) => fromLang === toLang),
|
||||
"A to-language should be supported as a from-language if it also exists in the from-language list."
|
||||
);
|
||||
|
||||
@@ -16,14 +16,6 @@ add_task(async function test_detected_language() {
|
||||
// Norwegian Bokmål
|
||||
{ fromLang: "nb", toLang: "en" },
|
||||
{ fromLang: "en", toLang: "nb" },
|
||||
|
||||
// Chinese (Simplified)
|
||||
{ fromLang: "zh-Hans", toLang: "en" },
|
||||
{ fromLang: "en", toLang: "zh-Hans" },
|
||||
|
||||
// Chinese (Traditional)
|
||||
{ fromLang: "zh-Hant", toLang: "en" },
|
||||
{ fromLang: "en", toLang: "zh-Hant" },
|
||||
],
|
||||
});
|
||||
|
||||
@@ -70,136 +62,6 @@ add_task(async function test_detected_language() {
|
||||
"The Norwegian macro language is detected, but it defaults to Norwegian Bokmål."
|
||||
);
|
||||
|
||||
Assert.deepEqual(
|
||||
await getDetectedLanguagesFor("zh-Hans"),
|
||||
{
|
||||
docLangTag: "zh-Hans",
|
||||
userLangTag: "en",
|
||||
isDocLangTagSupported: true,
|
||||
},
|
||||
"'zh-Hans' represents Simplified Chinese, commonly used in Mainland China, Malaysia, and Singapore."
|
||||
);
|
||||
|
||||
Assert.deepEqual(
|
||||
await getDetectedLanguagesFor("zh"),
|
||||
{
|
||||
docLangTag: "zh-Hans",
|
||||
userLangTag: "en",
|
||||
isDocLangTagSupported: true,
|
||||
},
|
||||
"The 'zh' language tag defaults to 'zh-Hans' (Simplified Chinese)."
|
||||
);
|
||||
|
||||
Assert.deepEqual(
|
||||
await getDetectedLanguagesFor("zh-CN"),
|
||||
{
|
||||
docLangTag: "zh-Hans",
|
||||
userLangTag: "en",
|
||||
isDocLangTagSupported: true,
|
||||
},
|
||||
"'zh-CN' maps to 'zh-Hans' (Simplified Chinese), commonly used in Mainland China."
|
||||
);
|
||||
|
||||
Assert.deepEqual(
|
||||
await getDetectedLanguagesFor("zh-MY"),
|
||||
{
|
||||
docLangTag: "zh-Hans",
|
||||
userLangTag: "en",
|
||||
isDocLangTagSupported: true,
|
||||
},
|
||||
"'zh-MY' maps to 'zh-Hans' (Simplified Chinese), commonly used in Malaysia."
|
||||
);
|
||||
|
||||
Assert.deepEqual(
|
||||
await getDetectedLanguagesFor("zh-SG"),
|
||||
{
|
||||
docLangTag: "zh-Hans",
|
||||
userLangTag: "en",
|
||||
isDocLangTagSupported: true,
|
||||
},
|
||||
"'zh-SG' maps to 'zh-Hans' (Simplified Chinese), commonly used in Singapore."
|
||||
);
|
||||
|
||||
Assert.deepEqual(
|
||||
await getDetectedLanguagesFor("zh-Hant"),
|
||||
{
|
||||
docLangTag: "zh-Hant",
|
||||
userLangTag: "en",
|
||||
isDocLangTagSupported: true,
|
||||
},
|
||||
"'zh-Hant' represents Traditional Chinese, commonly used in Hong Kong, Macau, and Taiwan."
|
||||
);
|
||||
|
||||
Assert.deepEqual(
|
||||
await getDetectedLanguagesFor("zh-TW"),
|
||||
{
|
||||
docLangTag: "zh-Hant",
|
||||
userLangTag: "en",
|
||||
isDocLangTagSupported: true,
|
||||
},
|
||||
"'zh-TW' maps to 'zh-Hant' (Traditional Chinese), commonly used in Taiwan."
|
||||
);
|
||||
|
||||
Assert.deepEqual(
|
||||
await getDetectedLanguagesFor("zh-HK"),
|
||||
{
|
||||
docLangTag: "zh-Hant",
|
||||
userLangTag: "en",
|
||||
isDocLangTagSupported: true,
|
||||
},
|
||||
"'zh-HK' maps to 'zh-Hant' (Traditional Chinese), commonly used in Hong Kong."
|
||||
);
|
||||
|
||||
Assert.deepEqual(
|
||||
await getDetectedLanguagesFor("zh-MO"),
|
||||
{
|
||||
docLangTag: "zh-Hant",
|
||||
userLangTag: "en",
|
||||
isDocLangTagSupported: true,
|
||||
},
|
||||
"'zh-MO' maps to 'zh-Hant' (Traditional Chinese), commonly used in Macau."
|
||||
);
|
||||
|
||||
Assert.deepEqual(
|
||||
await getDetectedLanguagesFor("zh-Hant-CN"),
|
||||
{
|
||||
docLangTag: "zh-Hant",
|
||||
userLangTag: "en",
|
||||
isDocLangTagSupported: true,
|
||||
},
|
||||
"An explicit 'Hant' script tag takes precedence, even though 'Hans' is commonly used in Mainland China."
|
||||
);
|
||||
|
||||
Assert.deepEqual(
|
||||
await getDetectedLanguagesFor("zh-Hans-TW"),
|
||||
{
|
||||
docLangTag: "zh-Hans",
|
||||
userLangTag: "en",
|
||||
isDocLangTagSupported: true,
|
||||
},
|
||||
"An explicit 'Hans' script tag takes precedence, even though 'Hant' is commonly used in Taiwan."
|
||||
);
|
||||
|
||||
Assert.deepEqual(
|
||||
await getDetectedLanguagesFor("es-Latn-ES"),
|
||||
{
|
||||
docLangTag: "es",
|
||||
userLangTag: "en",
|
||||
isDocLangTagSupported: true,
|
||||
},
|
||||
"A maximized lang tag with a script will resolve to the model's lang tag if the script matches the expectation."
|
||||
);
|
||||
|
||||
Assert.deepEqual(
|
||||
await getDetectedLanguagesFor("es-Hans"),
|
||||
{
|
||||
docLangTag: "es-Hans",
|
||||
userLangTag: "en",
|
||||
isDocLangTagSupported: false,
|
||||
},
|
||||
"A valid lang tag with a nonstandard script will be recognized, but is not resolvable to a model due to the script mismatch."
|
||||
);
|
||||
|
||||
Assert.deepEqual(
|
||||
await getDetectedLanguagesFor("spa"),
|
||||
{
|
||||
|
||||
@@ -36,7 +36,7 @@ add_task(async function test_preferred_language() {
|
||||
test() {
|
||||
Assert.deepEqual(
|
||||
TranslationsParent.getPreferredLanguages(),
|
||||
["en-US"],
|
||||
["en"],
|
||||
"When all locales are English, only English is preferred."
|
||||
);
|
||||
},
|
||||
@@ -49,7 +49,7 @@ add_task(async function test_preferred_language() {
|
||||
test() {
|
||||
Assert.deepEqual(
|
||||
TranslationsParent.getPreferredLanguages(),
|
||||
["en-US", "es-ES"],
|
||||
["en", "es"],
|
||||
"When the operating system differs, it is added to the end of the preferred languages."
|
||||
);
|
||||
},
|
||||
@@ -67,12 +67,11 @@ add_task(async function test_preferred_language() {
|
||||
"cs",
|
||||
"hu",
|
||||
// appLocales, notice that "en" is the last fallback.
|
||||
"pt-BR",
|
||||
"pt",
|
||||
"pl",
|
||||
"en-US",
|
||||
"en",
|
||||
// systemLocales
|
||||
"zh-TW",
|
||||
"zh-CN",
|
||||
"zh",
|
||||
"de",
|
||||
],
|
||||
"Demonstrate an unrealistic but complicated locale situation."
|
||||
|
||||
@@ -28,14 +28,14 @@ add_task(async function test_translations_actor_sync_update_models() {
|
||||
|
||||
is(
|
||||
decoder.decode(oldModels.model.buffer),
|
||||
`Mocked download: test-translation-models model.enes.intgemm.alphas.bin ${TranslationsParent.LANGUAGE_MODEL_MAJOR_VERSION_MAX}.0`,
|
||||
`The version ${TranslationsParent.LANGUAGE_MODEL_MAJOR_VERSION_MAX}.0 model is downloaded.`
|
||||
`Mocked download: test-translation-models model.enes.intgemm.alphas.bin ${TranslationsParent.LANGUAGE_MODEL_MAJOR_VERSION}.0`,
|
||||
`The version ${TranslationsParent.LANGUAGE_MODEL_MAJOR_VERSION}.0 model is downloaded.`
|
||||
);
|
||||
|
||||
const recordsToCreate = createRecordsForLanguagePair("en", "es");
|
||||
for (const newModelRecord of recordsToCreate) {
|
||||
newModelRecord.id = oldModels[newModelRecord.fileType].record.id;
|
||||
newModelRecord.version = `${TranslationsParent.LANGUAGE_MODEL_MAJOR_VERSION_MAX}.1`;
|
||||
newModelRecord.version = `${TranslationsParent.LANGUAGE_MODEL_MAJOR_VERSION}.1`;
|
||||
}
|
||||
|
||||
await modifyRemoteSettingsRecords(remoteClients.translationModels.client, {
|
||||
@@ -53,8 +53,8 @@ add_task(async function test_translations_actor_sync_update_models() {
|
||||
|
||||
is(
|
||||
decoder.decode(updatedModel.buffer),
|
||||
`Mocked download: test-translation-models model.enes.intgemm.alphas.bin ${TranslationsParent.LANGUAGE_MODEL_MAJOR_VERSION_MAX}.1`,
|
||||
`The version ${TranslationsParent.LANGUAGE_MODEL_MAJOR_VERSION_MAX}.1 model is downloaded.`
|
||||
`Mocked download: test-translation-models model.enes.intgemm.alphas.bin ${TranslationsParent.LANGUAGE_MODEL_MAJOR_VERSION}.1`,
|
||||
`The version ${TranslationsParent.LANGUAGE_MODEL_MAJOR_VERSION}.1 model is downloaded.`
|
||||
);
|
||||
|
||||
return cleanup();
|
||||
@@ -83,8 +83,8 @@ add_task(async function test_translations_actor_sync_delete_models() {
|
||||
|
||||
is(
|
||||
decoder.decode(model.buffer),
|
||||
`Mocked download: test-translation-models model.enes.intgemm.alphas.bin ${TranslationsParent.LANGUAGE_MODEL_MAJOR_VERSION_MAX}.0`,
|
||||
`The version ${TranslationsParent.LANGUAGE_MODEL_MAJOR_VERSION_MAX}.0 model is downloaded.`
|
||||
`Mocked download: test-translation-models model.enes.intgemm.alphas.bin ${TranslationsParent.LANGUAGE_MODEL_MAJOR_VERSION}.0`,
|
||||
`The version ${TranslationsParent.LANGUAGE_MODEL_MAJOR_VERSION}.0 model is downloaded.`
|
||||
);
|
||||
|
||||
info(
|
||||
@@ -132,8 +132,8 @@ add_task(async function test_translations_actor_sync_create_models() {
|
||||
const { languageModelFiles: originalFiles } = await modelsPromise;
|
||||
is(
|
||||
decoder.decode(originalFiles.model.buffer),
|
||||
`Mocked download: test-translation-models model.enes.intgemm.alphas.bin ${TranslationsParent.LANGUAGE_MODEL_MAJOR_VERSION_MAX}.0`,
|
||||
`The version ${TranslationsParent.LANGUAGE_MODEL_MAJOR_VERSION_MAX}.0 model is downloaded.`
|
||||
`Mocked download: test-translation-models model.enes.intgemm.alphas.bin ${TranslationsParent.LANGUAGE_MODEL_MAJOR_VERSION}.0`,
|
||||
`The version ${TranslationsParent.LANGUAGE_MODEL_MAJOR_VERSION}.0 model is downloaded.`
|
||||
);
|
||||
|
||||
const recordsToCreate = createRecordsForLanguagePair("en", "fr");
|
||||
@@ -153,17 +153,17 @@ add_task(async function test_translations_actor_sync_create_models() {
|
||||
|
||||
is(
|
||||
decoder.decode(vocab.buffer),
|
||||
`Mocked download: test-translation-models vocab.enfr.spm ${TranslationsParent.LANGUAGE_MODEL_MAJOR_VERSION_MAX}.0`,
|
||||
`Mocked download: test-translation-models vocab.enfr.spm ${TranslationsParent.LANGUAGE_MODEL_MAJOR_VERSION}.0`,
|
||||
"The en to fr vocab is downloaded."
|
||||
);
|
||||
is(
|
||||
decoder.decode(lex.buffer),
|
||||
`Mocked download: test-translation-models lex.50.50.enfr.s2t.bin ${TranslationsParent.LANGUAGE_MODEL_MAJOR_VERSION_MAX}.0`,
|
||||
`Mocked download: test-translation-models lex.50.50.enfr.s2t.bin ${TranslationsParent.LANGUAGE_MODEL_MAJOR_VERSION}.0`,
|
||||
"The en to fr lex is downloaded."
|
||||
);
|
||||
is(
|
||||
decoder.decode(model.buffer),
|
||||
`Mocked download: test-translation-models model.enfr.intgemm.alphas.bin ${TranslationsParent.LANGUAGE_MODEL_MAJOR_VERSION_MAX}.0`,
|
||||
`Mocked download: test-translation-models model.enfr.intgemm.alphas.bin ${TranslationsParent.LANGUAGE_MODEL_MAJOR_VERSION}.0`,
|
||||
"The en to fr model is downloaded."
|
||||
);
|
||||
|
||||
@@ -192,13 +192,13 @@ add_task(
|
||||
const { languageModelFiles: originalFiles } = await modelsPromise;
|
||||
is(
|
||||
decoder.decode(originalFiles.model.buffer),
|
||||
`Mocked download: test-translation-models model.enes.intgemm.alphas.bin ${TranslationsParent.LANGUAGE_MODEL_MAJOR_VERSION_MAX}.0`,
|
||||
`The version ${TranslationsParent.LANGUAGE_MODEL_MAJOR_VERSION_MAX}.0 model is downloaded.`
|
||||
`Mocked download: test-translation-models model.enes.intgemm.alphas.bin ${TranslationsParent.LANGUAGE_MODEL_MAJOR_VERSION}.0`,
|
||||
`The version ${TranslationsParent.LANGUAGE_MODEL_MAJOR_VERSION}.0 model is downloaded.`
|
||||
);
|
||||
|
||||
const recordsToCreate = createRecordsForLanguagePair("en", "es");
|
||||
for (const newModelRecord of recordsToCreate) {
|
||||
newModelRecord.version = `${TranslationsParent.LANGUAGE_MODEL_MAJOR_VERSION_MAX}.1`;
|
||||
newModelRecord.version = `${TranslationsParent.LANGUAGE_MODEL_MAJOR_VERSION}.1`;
|
||||
}
|
||||
|
||||
await modifyRemoteSettingsRecords(remoteClients.translationModels.client, {
|
||||
@@ -216,18 +216,18 @@ add_task(
|
||||
|
||||
is(
|
||||
decoder.decode(vocab.buffer),
|
||||
`Mocked download: test-translation-models vocab.enes.spm ${TranslationsParent.LANGUAGE_MODEL_MAJOR_VERSION_MAX}.1`,
|
||||
`The ${TranslationsParent.LANGUAGE_MODEL_MAJOR_VERSION_MAX}.1 vocab is downloaded.`
|
||||
`Mocked download: test-translation-models vocab.enes.spm ${TranslationsParent.LANGUAGE_MODEL_MAJOR_VERSION}.1`,
|
||||
`The ${TranslationsParent.LANGUAGE_MODEL_MAJOR_VERSION}.1 vocab is downloaded.`
|
||||
);
|
||||
is(
|
||||
decoder.decode(lex.buffer),
|
||||
`Mocked download: test-translation-models lex.50.50.enes.s2t.bin ${TranslationsParent.LANGUAGE_MODEL_MAJOR_VERSION_MAX}.1`,
|
||||
`The ${TranslationsParent.LANGUAGE_MODEL_MAJOR_VERSION_MAX}.1 lex is downloaded.`
|
||||
`Mocked download: test-translation-models lex.50.50.enes.s2t.bin ${TranslationsParent.LANGUAGE_MODEL_MAJOR_VERSION}.1`,
|
||||
`The ${TranslationsParent.LANGUAGE_MODEL_MAJOR_VERSION}.1 lex is downloaded.`
|
||||
);
|
||||
is(
|
||||
decoder.decode(model.buffer),
|
||||
`Mocked download: test-translation-models model.enes.intgemm.alphas.bin ${TranslationsParent.LANGUAGE_MODEL_MAJOR_VERSION_MAX}.1`,
|
||||
`The ${TranslationsParent.LANGUAGE_MODEL_MAJOR_VERSION_MAX}.1 model is downloaded.`
|
||||
`Mocked download: test-translation-models model.enes.intgemm.alphas.bin ${TranslationsParent.LANGUAGE_MODEL_MAJOR_VERSION}.1`,
|
||||
`The ${TranslationsParent.LANGUAGE_MODEL_MAJOR_VERSION}.1 model is downloaded.`
|
||||
);
|
||||
|
||||
return cleanup();
|
||||
@@ -256,8 +256,8 @@ add_task(
|
||||
const { languageModelFiles: originalFiles } = await modelsPromise;
|
||||
is(
|
||||
decoder.decode(originalFiles.model.buffer),
|
||||
`Mocked download: test-translation-models model.enes.intgemm.alphas.bin ${TranslationsParent.LANGUAGE_MODEL_MAJOR_VERSION_MAX}.0`,
|
||||
`The version ${TranslationsParent.LANGUAGE_MODEL_MAJOR_VERSION_MAX}.0 model is downloaded.`
|
||||
`Mocked download: test-translation-models model.enes.intgemm.alphas.bin ${TranslationsParent.LANGUAGE_MODEL_MAJOR_VERSION}.0`,
|
||||
`The version ${TranslationsParent.LANGUAGE_MODEL_MAJOR_VERSION}.0 model is downloaded.`
|
||||
);
|
||||
|
||||
const recordsToCreate = createRecordsForLanguagePair("en", "es");
|
||||
@@ -280,18 +280,18 @@ add_task(
|
||||
|
||||
is(
|
||||
decoder.decode(vocab.buffer),
|
||||
`Mocked download: test-translation-models vocab.enes.spm ${TranslationsParent.LANGUAGE_MODEL_MAJOR_VERSION_MAX}.0`,
|
||||
`The ${TranslationsParent.LANGUAGE_MODEL_MAJOR_VERSION_MAX}.0 vocab is downloaded.`
|
||||
`Mocked download: test-translation-models vocab.enes.spm ${TranslationsParent.LANGUAGE_MODEL_MAJOR_VERSION}.0`,
|
||||
`The ${TranslationsParent.LANGUAGE_MODEL_MAJOR_VERSION}.0 vocab is downloaded.`
|
||||
);
|
||||
is(
|
||||
decoder.decode(lex.buffer),
|
||||
`Mocked download: test-translation-models lex.50.50.enes.s2t.bin ${TranslationsParent.LANGUAGE_MODEL_MAJOR_VERSION_MAX}.0`,
|
||||
`The ${TranslationsParent.LANGUAGE_MODEL_MAJOR_VERSION_MAX}.0 lex is downloaded.`
|
||||
`Mocked download: test-translation-models lex.50.50.enes.s2t.bin ${TranslationsParent.LANGUAGE_MODEL_MAJOR_VERSION}.0`,
|
||||
`The ${TranslationsParent.LANGUAGE_MODEL_MAJOR_VERSION}.0 lex is downloaded.`
|
||||
);
|
||||
is(
|
||||
decoder.decode(model.buffer),
|
||||
`Mocked download: test-translation-models model.enes.intgemm.alphas.bin ${TranslationsParent.LANGUAGE_MODEL_MAJOR_VERSION_MAX}.0`,
|
||||
`The ${TranslationsParent.LANGUAGE_MODEL_MAJOR_VERSION_MAX}.0 model is downloaded.`
|
||||
`Mocked download: test-translation-models model.enes.intgemm.alphas.bin ${TranslationsParent.LANGUAGE_MODEL_MAJOR_VERSION}.0`,
|
||||
`The ${TranslationsParent.LANGUAGE_MODEL_MAJOR_VERSION}.0 model is downloaded.`
|
||||
);
|
||||
|
||||
return cleanup();
|
||||
@@ -313,7 +313,7 @@ add_task(async function test_translations_actor_sync_rollback_models() {
|
||||
|
||||
const newRecords = createRecordsForLanguagePair("en", "es");
|
||||
for (const newModelRecord of newRecords) {
|
||||
newModelRecord.version = `${TranslationsParent.LANGUAGE_MODEL_MAJOR_VERSION_MAX}.1`;
|
||||
newModelRecord.version = `${TranslationsParent.LANGUAGE_MODEL_MAJOR_VERSION}.1`;
|
||||
}
|
||||
|
||||
await modifyRemoteSettingsRecords(remoteClients.translationModels.client, {
|
||||
@@ -330,8 +330,8 @@ add_task(async function test_translations_actor_sync_rollback_models() {
|
||||
const { languageModelFiles: originalFiles } = await modelsPromise;
|
||||
is(
|
||||
decoder.decode(originalFiles.model.buffer),
|
||||
`Mocked download: test-translation-models model.enes.intgemm.alphas.bin ${TranslationsParent.LANGUAGE_MODEL_MAJOR_VERSION_MAX}.1`,
|
||||
`The version ${TranslationsParent.LANGUAGE_MODEL_MAJOR_VERSION_MAX}.1 model is downloaded.`
|
||||
`Mocked download: test-translation-models model.enes.intgemm.alphas.bin ${TranslationsParent.LANGUAGE_MODEL_MAJOR_VERSION}.1`,
|
||||
`The version ${TranslationsParent.LANGUAGE_MODEL_MAJOR_VERSION}.1 model is downloaded.`
|
||||
);
|
||||
|
||||
await modifyRemoteSettingsRecords(remoteClients.translationModels.client, {
|
||||
@@ -349,18 +349,18 @@ add_task(async function test_translations_actor_sync_rollback_models() {
|
||||
|
||||
is(
|
||||
decoder.decode(vocab.buffer),
|
||||
`Mocked download: test-translation-models vocab.enes.spm ${TranslationsParent.LANGUAGE_MODEL_MAJOR_VERSION_MAX}.0`,
|
||||
`The ${TranslationsParent.LANGUAGE_MODEL_MAJOR_VERSION_MAX}.0 vocab is downloaded.`
|
||||
`Mocked download: test-translation-models vocab.enes.spm ${TranslationsParent.LANGUAGE_MODEL_MAJOR_VERSION}.0`,
|
||||
`The ${TranslationsParent.LANGUAGE_MODEL_MAJOR_VERSION}.0 vocab is downloaded.`
|
||||
);
|
||||
is(
|
||||
decoder.decode(lex.buffer),
|
||||
`Mocked download: test-translation-models lex.50.50.enes.s2t.bin ${TranslationsParent.LANGUAGE_MODEL_MAJOR_VERSION_MAX}.0`,
|
||||
`The ${TranslationsParent.LANGUAGE_MODEL_MAJOR_VERSION_MAX}.0 lex is downloaded.`
|
||||
`Mocked download: test-translation-models lex.50.50.enes.s2t.bin ${TranslationsParent.LANGUAGE_MODEL_MAJOR_VERSION}.0`,
|
||||
`The ${TranslationsParent.LANGUAGE_MODEL_MAJOR_VERSION}.0 lex is downloaded.`
|
||||
);
|
||||
is(
|
||||
decoder.decode(model.buffer),
|
||||
`Mocked download: test-translation-models model.enes.intgemm.alphas.bin ${TranslationsParent.LANGUAGE_MODEL_MAJOR_VERSION_MAX}.0`,
|
||||
`The ${TranslationsParent.LANGUAGE_MODEL_MAJOR_VERSION_MAX}.0 model is downloaded.`
|
||||
`Mocked download: test-translation-models model.enes.intgemm.alphas.bin ${TranslationsParent.LANGUAGE_MODEL_MAJOR_VERSION}.0`,
|
||||
`The ${TranslationsParent.LANGUAGE_MODEL_MAJOR_VERSION}.0 model is downloaded.`
|
||||
);
|
||||
|
||||
return cleanup();
|
||||
|
||||
@@ -26,15 +26,13 @@ add_task(async function test_translations_actor_sync_update_wasm() {
|
||||
);
|
||||
|
||||
const newWasmRecord = createWasmRecord();
|
||||
const [oldWasmRecord] =
|
||||
await TranslationsParent.getMaxSupportedVersionRecords(
|
||||
remoteClients.translationsWasm.client,
|
||||
{
|
||||
filters: { name: "bergamot-translator" },
|
||||
minSupportedMajorVersion: TranslationsParent.BERGAMOT_MAJOR_VERSION,
|
||||
maxSupportedMajorVersion: TranslationsParent.BERGAMOT_MAJOR_VERSION,
|
||||
}
|
||||
);
|
||||
const [oldWasmRecord] = await TranslationsParent.getMaxVersionRecords(
|
||||
remoteClients.translationsWasm.client,
|
||||
{
|
||||
filters: { name: "bergamot-translator" },
|
||||
majorVersion: TranslationsParent.BERGAMOT_MAJOR_VERSION,
|
||||
}
|
||||
);
|
||||
|
||||
newWasmRecord.id = oldWasmRecord.id;
|
||||
newWasmRecord.version = `${TranslationsParent.BERGAMOT_MAJOR_VERSION}.1`;
|
||||
@@ -75,15 +73,13 @@ add_task(async function test_translations_actor_sync_delete_wasm() {
|
||||
`The version ${TranslationsParent.BERGAMOT_MAJOR_VERSION}.0 model is downloaded.`
|
||||
);
|
||||
|
||||
const [oldWasmRecord] =
|
||||
await TranslationsParent.getMaxSupportedVersionRecords(
|
||||
remoteClients.translationsWasm.client,
|
||||
{
|
||||
filters: { name: "bergamot-translator" },
|
||||
minSupportedMajorVersion: TranslationsParent.BERGAMOT_MAJOR_VERSION,
|
||||
maxSupportedMajorVersion: TranslationsParent.BERGAMOT_MAJOR_VERSION,
|
||||
}
|
||||
);
|
||||
const [oldWasmRecord] = await TranslationsParent.getMaxVersionRecords(
|
||||
remoteClients.translationsWasm.client,
|
||||
{
|
||||
filters: { name: "bergamot-translator" },
|
||||
majorVersion: TranslationsParent.BERGAMOT_MAJOR_VERSION,
|
||||
}
|
||||
);
|
||||
|
||||
await modifyRemoteSettingsRecords(remoteClients.translationsWasm.client, {
|
||||
recordsToDelete: [oldWasmRecord],
|
||||
|
||||
@@ -4,311 +4,78 @@
|
||||
"use strict";
|
||||
|
||||
add_task(async function test_remote_settings_versioning() {
|
||||
const testCases = [
|
||||
const tests = [
|
||||
{
|
||||
minSupportedMajorVersion: 1,
|
||||
maxSupportedMajorVersion: 3,
|
||||
currentBestVersion: null,
|
||||
contendingVersion: "1.0a1",
|
||||
expectContendingIsBetter: true,
|
||||
description:
|
||||
"Contending pre-release version aligned with minimum supported major version without current best version",
|
||||
majorVersion: 1,
|
||||
existingVersion: "1.0",
|
||||
nextVersion: "1.1",
|
||||
expectation: true,
|
||||
},
|
||||
{
|
||||
minSupportedMajorVersion: 1,
|
||||
maxSupportedMajorVersion: 3,
|
||||
currentBestVersion: null,
|
||||
contendingVersion: "1.0",
|
||||
expectContendingIsBetter: true,
|
||||
description:
|
||||
"Contending release version aligned with minimum supported major version without current best version",
|
||||
majorVersion: 1,
|
||||
existingVersion: null,
|
||||
nextVersion: "1.1",
|
||||
expectation: true,
|
||||
},
|
||||
{
|
||||
minSupportedMajorVersion: 1,
|
||||
maxSupportedMajorVersion: 3,
|
||||
currentBestVersion: null,
|
||||
contendingVersion: "2.0a1",
|
||||
expectContendingIsBetter: true,
|
||||
description:
|
||||
"Contending pre-release version between supported major versions without current best version",
|
||||
majorVersion: 1,
|
||||
existingVersion: null,
|
||||
nextVersion: "1.0beta",
|
||||
expectation: true,
|
||||
},
|
||||
{
|
||||
minSupportedMajorVersion: 1,
|
||||
maxSupportedMajorVersion: 3,
|
||||
currentBestVersion: null,
|
||||
contendingVersion: "2.0",
|
||||
expectContendingIsBetter: true,
|
||||
description:
|
||||
"Contending release version between supported major versions without current best version",
|
||||
majorVersion: 1,
|
||||
existingVersion: null,
|
||||
nextVersion: "1.0a",
|
||||
expectation: true,
|
||||
},
|
||||
{
|
||||
minSupportedMajorVersion: 1,
|
||||
maxSupportedMajorVersion: 3,
|
||||
currentBestVersion: null,
|
||||
contendingVersion: "3.0a1",
|
||||
expectContendingIsBetter: true,
|
||||
description:
|
||||
"Contending pre-release version with maximum supported major version without current best version",
|
||||
majorVersion: 2,
|
||||
existingVersion: null,
|
||||
nextVersion: "1.0a",
|
||||
expectation: false,
|
||||
},
|
||||
{
|
||||
minSupportedMajorVersion: 1,
|
||||
maxSupportedMajorVersion: 3,
|
||||
currentBestVersion: null,
|
||||
contendingVersion: "3.0",
|
||||
expectContendingIsBetter: true,
|
||||
description:
|
||||
"Contending release version aligned with maximum supported major version without current best version",
|
||||
majorVersion: 2,
|
||||
existingVersion: "2.0",
|
||||
nextVersion: "1.0a",
|
||||
expectation: false,
|
||||
},
|
||||
{
|
||||
minSupportedMajorVersion: 1,
|
||||
maxSupportedMajorVersion: 1,
|
||||
currentBestVersion: null,
|
||||
contendingVersion: "1.0a1",
|
||||
expectContendingIsBetter: true,
|
||||
description:
|
||||
"Contending pre-release version aligned with minimum and maximum supported major versions without current best version",
|
||||
majorVersion: 2,
|
||||
existingVersion: "2.1",
|
||||
nextVersion: "3.2",
|
||||
expectation: false,
|
||||
},
|
||||
{
|
||||
minSupportedMajorVersion: 1,
|
||||
maxSupportedMajorVersion: 1,
|
||||
currentBestVersion: null,
|
||||
contendingVersion: "1.0",
|
||||
expectContendingIsBetter: true,
|
||||
description:
|
||||
"Contending release version aligned with minimum and maximum supported major versions without current best version",
|
||||
majorVersion: 2,
|
||||
existingVersion: null,
|
||||
nextVersion: "3.2",
|
||||
expectation: false,
|
||||
},
|
||||
{
|
||||
minSupportedMajorVersion: 1,
|
||||
maxSupportedMajorVersion: 2,
|
||||
currentBestVersion: "1.0a1",
|
||||
contendingVersion: "1.0a2",
|
||||
expectContendingIsBetter: true,
|
||||
description:
|
||||
"Contending pre-release tag version is larger than current pre-release tag version",
|
||||
},
|
||||
{
|
||||
minSupportedMajorVersion: 1,
|
||||
maxSupportedMajorVersion: 2,
|
||||
currentBestVersion: "1.0a2",
|
||||
contendingVersion: "1.1a1",
|
||||
expectContendingIsBetter: true,
|
||||
description:
|
||||
"Contending pre-release minor version is larger than current pre-release version",
|
||||
},
|
||||
{
|
||||
minSupportedMajorVersion: 1,
|
||||
maxSupportedMajorVersion: 2,
|
||||
currentBestVersion: "1.0a2",
|
||||
contendingVersion: "2.0a1",
|
||||
expectContendingIsBetter: true,
|
||||
description:
|
||||
"Contending pre-release major version is larger than current pre-release version",
|
||||
},
|
||||
{
|
||||
minSupportedMajorVersion: 1,
|
||||
maxSupportedMajorVersion: 2,
|
||||
currentBestVersion: "1.1",
|
||||
contendingVersion: "2.0a1",
|
||||
expectContendingIsBetter: true,
|
||||
description:
|
||||
"Contending pre-release major version is larger than current release major version",
|
||||
},
|
||||
{
|
||||
minSupportedMajorVersion: 1,
|
||||
maxSupportedMajorVersion: 2,
|
||||
currentBestVersion: "1.0",
|
||||
contendingVersion: "1.1a1",
|
||||
expectContendingIsBetter: true,
|
||||
description:
|
||||
"Contending pre-release minor version is larger than the current release minor version within the same major version",
|
||||
},
|
||||
{
|
||||
minSupportedMajorVersion: 1,
|
||||
maxSupportedMajorVersion: 2,
|
||||
currentBestVersion: "1.0",
|
||||
contendingVersion: "1.1",
|
||||
expectContendingIsBetter: true,
|
||||
description:
|
||||
"Contending release minor version is larger than the current release minor version within the same major version",
|
||||
},
|
||||
{
|
||||
minSupportedMajorVersion: 1,
|
||||
maxSupportedMajorVersion: 2,
|
||||
currentBestVersion: "1.0a1",
|
||||
contendingVersion: "1.0",
|
||||
expectContendingIsBetter: true,
|
||||
description:
|
||||
"Contending release major version is equal to pre-release major version",
|
||||
},
|
||||
{
|
||||
minSupportedMajorVersion: 1,
|
||||
maxSupportedMajorVersion: 2,
|
||||
currentBestVersion: "1.0a2",
|
||||
contendingVersion: "1.0a1",
|
||||
expectContendingIsBetter: false,
|
||||
description:
|
||||
"Contending pre-release tag version is smaller than current pre-release version",
|
||||
},
|
||||
{
|
||||
minSupportedMajorVersion: 1,
|
||||
maxSupportedMajorVersion: 2,
|
||||
currentBestVersion: "1.1a1",
|
||||
contendingVersion: "1.0a1",
|
||||
expectContendingIsBetter: false,
|
||||
description:
|
||||
"Contending pre-release minor version is smaller than current pre-release minor version",
|
||||
},
|
||||
{
|
||||
minSupportedMajorVersion: 1,
|
||||
maxSupportedMajorVersion: 2,
|
||||
currentBestVersion: "2.0a1",
|
||||
contendingVersion: "1.0a1",
|
||||
expectContendingIsBetter: false,
|
||||
description:
|
||||
"Contending pre-release major version is smaller than current pre-release major version",
|
||||
},
|
||||
{
|
||||
minSupportedMajorVersion: 1,
|
||||
maxSupportedMajorVersion: 2,
|
||||
currentBestVersion: "1.1a1",
|
||||
contendingVersion: "1.0",
|
||||
expectContendingIsBetter: false,
|
||||
description:
|
||||
"Contending release minor version is smaller than current pre-release minor version",
|
||||
},
|
||||
{
|
||||
minSupportedMajorVersion: 1,
|
||||
maxSupportedMajorVersion: 2,
|
||||
currentBestVersion: "1.0",
|
||||
contendingVersion: "1.0a1",
|
||||
expectContendingIsBetter: false,
|
||||
description:
|
||||
"Contending pre-release version is smaller than the current release version of the same major version",
|
||||
},
|
||||
{
|
||||
minSupportedMajorVersion: 1,
|
||||
maxSupportedMajorVersion: 2,
|
||||
currentBestVersion: "1.1",
|
||||
contendingVersion: "1.1a1",
|
||||
expectContendingIsBetter: false,
|
||||
description:
|
||||
"Contending pre-release version is of the same minor version as current best release version",
|
||||
},
|
||||
{
|
||||
minSupportedMajorVersion: 1,
|
||||
maxSupportedMajorVersion: 2,
|
||||
currentBestVersion: "1.1",
|
||||
contendingVersion: "1.0",
|
||||
expectContendingIsBetter: false,
|
||||
description:
|
||||
"Contending release minor version is smaller than the current release minor version within the same major version",
|
||||
},
|
||||
{
|
||||
minSupportedMajorVersion: 1,
|
||||
maxSupportedMajorVersion: 2,
|
||||
currentBestVersion: "2.0a1",
|
||||
contendingVersion: "1.0",
|
||||
expectContendingIsBetter: false,
|
||||
description:
|
||||
"Contending release major version is smaller than current pre-release major version",
|
||||
},
|
||||
{
|
||||
minSupportedMajorVersion: 2,
|
||||
maxSupportedMajorVersion: 4,
|
||||
currentBestVersion: null,
|
||||
contendingVersion: "1.0a1",
|
||||
expectContendingIsBetter: false,
|
||||
description:
|
||||
"Contending pre-release version is smaller than the minimum supported major version without current best version",
|
||||
},
|
||||
{
|
||||
minSupportedMajorVersion: 2,
|
||||
maxSupportedMajorVersion: 4,
|
||||
currentBestVersion: "3.0a1",
|
||||
contendingVersion: "1.0a1",
|
||||
expectContendingIsBetter: false,
|
||||
description:
|
||||
"Contending pre-release version is smaller than the minimum supported major version with current best version",
|
||||
},
|
||||
{
|
||||
minSupportedMajorVersion: 2,
|
||||
maxSupportedMajorVersion: 4,
|
||||
currentBestVersion: null,
|
||||
contendingVersion: "1.0",
|
||||
expectContendingIsBetter: false,
|
||||
description:
|
||||
"Contending release version is smaller than the minimum supported major version without current best version",
|
||||
},
|
||||
{
|
||||
minSupportedMajorVersion: 2,
|
||||
maxSupportedMajorVersion: 4,
|
||||
currentBestVersion: "3.0a1",
|
||||
contendingVersion: "1.0",
|
||||
expectContendingIsBetter: false,
|
||||
description:
|
||||
"Contending release version is smaller than the minimum supported major version with current best version",
|
||||
},
|
||||
{
|
||||
minSupportedMajorVersion: 2,
|
||||
maxSupportedMajorVersion: 4,
|
||||
currentBestVersion: null,
|
||||
contendingVersion: "5.0a1",
|
||||
expectContendingIsBetter: false,
|
||||
description:
|
||||
"Contending pre-release version is larger than the maximum supported major version without current best version",
|
||||
},
|
||||
{
|
||||
minSupportedMajorVersion: 2,
|
||||
maxSupportedMajorVersion: 4,
|
||||
currentBestVersion: "3.0a1",
|
||||
contendingVersion: "5.0a1",
|
||||
expectContendingIsBetter: false,
|
||||
description:
|
||||
"Contending pre-release version is larger than the maximum supported major version with current best version",
|
||||
},
|
||||
{
|
||||
minSupportedMajorVersion: 2,
|
||||
maxSupportedMajorVersion: 4,
|
||||
currentBestVersion: null,
|
||||
contendingVersion: "5.0",
|
||||
expectContendingIsBetter: false,
|
||||
description:
|
||||
"Contending release version is larger than the maximum supported major version without current best version",
|
||||
},
|
||||
{
|
||||
minSupportedMajorVersion: 2,
|
||||
maxSupportedMajorVersion: 4,
|
||||
currentBestVersion: "3.0a1",
|
||||
contendingVersion: "5.0",
|
||||
expectContendingIsBetter: false,
|
||||
description:
|
||||
"Contending release version is larger than the maximum supported major version with current best version",
|
||||
majorVersion: 1,
|
||||
nextVersion: "1.0",
|
||||
existingVersion: undefined,
|
||||
expectation: true,
|
||||
},
|
||||
];
|
||||
|
||||
for (const {
|
||||
minSupportedMajorVersion,
|
||||
maxSupportedMajorVersion,
|
||||
currentBestVersion,
|
||||
contendingVersion,
|
||||
expectContendingIsBetter,
|
||||
description,
|
||||
} of testCases) {
|
||||
majorVersion,
|
||||
existingVersion,
|
||||
nextVersion,
|
||||
expectation,
|
||||
} of tests) {
|
||||
is(
|
||||
TranslationsParent.isBetterRecordVersion(
|
||||
minSupportedMajorVersion,
|
||||
maxSupportedMajorVersion,
|
||||
contendingVersion,
|
||||
currentBestVersion
|
||||
majorVersion,
|
||||
nextVersion,
|
||||
existingVersion
|
||||
),
|
||||
expectContendingIsBetter,
|
||||
`
|
||||
${description}:
|
||||
|
||||
Given a supported major version range from min(${minSupportedMajorVersion}) to max(${maxSupportedMajorVersion}),
|
||||
a current best supported version of ${currentBestVersion}, with a contending version of ${contendingVersion},
|
||||
the contending version (${contendingVersion}) is ${expectContendingIsBetter ? "" : "not "} better than the current best version (${currentBestVersion}).
|
||||
`
|
||||
expectation,
|
||||
`Given a major version of ${majorVersion}, an existing version ${existingVersion} ` +
|
||||
`and a next version of ${nextVersion}, is the next version is ` +
|
||||
`${expectation ? "" : "not "}best.`
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -271,12 +271,10 @@ add_task(async function test_get_records_with_multiple_versions() {
|
||||
.client,
|
||||
});
|
||||
|
||||
const retrievedRecords =
|
||||
await TranslationsParent.getMaxSupportedVersionRecords(client, {
|
||||
lookupKey,
|
||||
minSupportedMajorVersion: 1,
|
||||
maxSupportedMajorVersion: 1,
|
||||
});
|
||||
const retrievedRecords = await TranslationsParent.getMaxVersionRecords(
|
||||
client,
|
||||
{ lookupKey, majorVersion: 1 }
|
||||
);
|
||||
|
||||
for (const record of retrievedRecords) {
|
||||
is(
|
||||
|
||||
@@ -12,9 +12,6 @@ const { EngineProcess } = ChromeUtils.importESModule(
|
||||
const { TranslationsPanelShared } = ChromeUtils.importESModule(
|
||||
"chrome://browser/content/translations/TranslationsPanelShared.sys.mjs"
|
||||
);
|
||||
const { TranslationsUtils } = ChromeUtils.importESModule(
|
||||
"chrome://global/content/translations/TranslationsUtils.sys.mjs"
|
||||
);
|
||||
|
||||
// Avoid about:blank's non-standard behavior.
|
||||
const BLANK_PAGE =
|
||||
@@ -1375,7 +1372,7 @@ function createRecordsForLanguagePair(fromLang, toLang) {
|
||||
fromLang,
|
||||
toLang,
|
||||
fileType,
|
||||
version: TranslationsParent.LANGUAGE_MODEL_MAJOR_VERSION_MAX + ".0",
|
||||
version: TranslationsParent.LANGUAGE_MODEL_MAJOR_VERSION + ".0",
|
||||
last_modified: Date.now(),
|
||||
schema: Date.now(),
|
||||
attachment: JSON.parse(JSON.stringify(attachment)), // Making a deep copy.
|
||||
|
||||
Reference in New Issue
Block a user