287 lines
8.3 KiB
JavaScript
287 lines
8.3 KiB
JavaScript
/* 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/. */
|
|
|
|
const { getAddonAndLocalAPIsMocker } = ChromeUtils.importESModule(
|
|
"resource://testing-common/LangPackMatcherTestUtils.sys.mjs"
|
|
);
|
|
const { LangPackMatcher } = ChromeUtils.importESModule(
|
|
"resource://gre/modules/LangPackMatcher.sys.mjs"
|
|
);
|
|
const { sinon } = ChromeUtils.importESModule(
|
|
"resource://testing-common/Sinon.sys.mjs"
|
|
);
|
|
|
|
const sandbox = sinon.createSandbox();
|
|
const mockAddonAndLocaleAPIs = getAddonAndLocalAPIsMocker(this, sandbox);
|
|
|
|
add_task(function initSandbox() {
|
|
registerCleanupFunction(() => {
|
|
sandbox.restore();
|
|
});
|
|
});
|
|
|
|
add_task(function test_appLocaleLanguageMismatch() {
|
|
sandbox.restore();
|
|
mockAddonAndLocaleAPIs({
|
|
systemLocale: "es-ES",
|
|
appLocale: "en-US",
|
|
});
|
|
|
|
deepEqual(LangPackMatcher.getAppAndSystemLocaleInfo(), {
|
|
systemLocaleRaw: "es-ES",
|
|
systemLocale: { baseName: "es-ES", language: "es", region: "ES" },
|
|
appLocaleRaw: "en-US",
|
|
appLocale: { baseName: "en-US", language: "en", region: "US" },
|
|
matchType: "language-mismatch",
|
|
canLiveReload: true,
|
|
displayNames: {
|
|
systemLanguage: "Español (ES)",
|
|
appLanguage: "English (US)",
|
|
},
|
|
});
|
|
});
|
|
|
|
add_task(function test_appLocaleRegionMismatch() {
|
|
sandbox.restore();
|
|
mockAddonAndLocaleAPIs({
|
|
sandbox,
|
|
systemLocale: "en-CA",
|
|
appLocale: "en-US",
|
|
});
|
|
|
|
deepEqual(LangPackMatcher.getAppAndSystemLocaleInfo(), {
|
|
systemLocaleRaw: "en-CA",
|
|
systemLocale: { baseName: "en-CA", language: "en", region: "CA" },
|
|
appLocaleRaw: "en-US",
|
|
appLocale: { baseName: "en-US", language: "en", region: "US" },
|
|
matchType: "region-mismatch",
|
|
canLiveReload: true,
|
|
displayNames: {
|
|
systemLanguage: "English (CA)",
|
|
appLanguage: "English (US)",
|
|
},
|
|
});
|
|
});
|
|
|
|
add_task(function test_appLocaleScriptMismatch() {
|
|
sandbox.restore();
|
|
// Script mismatch:
|
|
mockAddonAndLocaleAPIs({
|
|
sandbox,
|
|
systemLocale: "zh-Hans-CN",
|
|
appLocale: "zh-CN",
|
|
});
|
|
|
|
deepEqual(LangPackMatcher.getAppAndSystemLocaleInfo(), {
|
|
systemLocaleRaw: "zh-Hans-CN",
|
|
systemLocale: { baseName: "zh-Hans-CN", language: "zh", region: "CN" },
|
|
appLocaleRaw: "zh-CN",
|
|
appLocale: { baseName: "zh-CN", language: "zh", region: "CN" },
|
|
matchType: "match",
|
|
canLiveReload: true,
|
|
displayNames: {
|
|
systemLanguage: "Chinese (Hans, China)",
|
|
appLanguage: "简体中文",
|
|
},
|
|
});
|
|
});
|
|
|
|
add_task(function test_appLocaleInvalidSystem() {
|
|
sandbox.restore();
|
|
// Script mismatch:
|
|
mockAddonAndLocaleAPIs({
|
|
sandbox,
|
|
systemLocale: "Not valid",
|
|
appLocale: "en-US",
|
|
});
|
|
|
|
deepEqual(LangPackMatcher.getAppAndSystemLocaleInfo(), {
|
|
systemLocaleRaw: "Not valid",
|
|
systemLocale: null,
|
|
appLocaleRaw: "en-US",
|
|
appLocale: { baseName: "en-US", language: "en", region: "US" },
|
|
matchType: "unknown",
|
|
canLiveReload: null,
|
|
displayNames: { systemLanguage: null, appLanguage: "English (US)" },
|
|
});
|
|
});
|
|
|
|
add_task(function test_bidiSwitchDisabled() {
|
|
Services.prefs.setBoolPref(
|
|
"intl.multilingual.liveReloadBidirectional",
|
|
false
|
|
);
|
|
sandbox.restore();
|
|
// Script mismatch:
|
|
mockAddonAndLocaleAPIs({
|
|
sandbox,
|
|
systemLocale: "ar-EG",
|
|
appLocale: "en-US",
|
|
});
|
|
|
|
deepEqual(LangPackMatcher.getAppAndSystemLocaleInfo(), {
|
|
systemLocaleRaw: "ar-EG",
|
|
systemLocale: { baseName: "ar-EG", language: "ar", region: "EG" },
|
|
appLocaleRaw: "en-US",
|
|
appLocale: { baseName: "en-US", language: "en", region: "US" },
|
|
matchType: "language-mismatch",
|
|
canLiveReload: false,
|
|
displayNames: {
|
|
systemLanguage: "Arabic (Egypt)",
|
|
appLanguage: "English (US)",
|
|
},
|
|
});
|
|
Services.prefs.clearUserPref("intl.multilingual.liveReloadBidirectional");
|
|
});
|
|
|
|
add_task(async function test_bidiSwitchEnabled() {
|
|
Services.prefs.setBoolPref("intl.multilingual.liveReloadBidirectional", true);
|
|
sandbox.restore();
|
|
// Script mismatch:
|
|
mockAddonAndLocaleAPIs({
|
|
sandbox,
|
|
systemLocale: "ar-EG",
|
|
appLocale: "en-US",
|
|
});
|
|
|
|
deepEqual(LangPackMatcher.getAppAndSystemLocaleInfo(), {
|
|
systemLocaleRaw: "ar-EG",
|
|
systemLocale: { baseName: "ar-EG", language: "ar", region: "EG" },
|
|
appLocaleRaw: "en-US",
|
|
appLocale: { baseName: "en-US", language: "en", region: "US" },
|
|
matchType: "language-mismatch",
|
|
canLiveReload: true,
|
|
displayNames: {
|
|
systemLanguage: "Arabic (Egypt)",
|
|
appLanguage: "English (US)",
|
|
},
|
|
});
|
|
|
|
Services.prefs.clearUserPref("intl.multilingual.liveReloadBidirectional");
|
|
});
|
|
|
|
function shuffle(array) {
|
|
return array
|
|
.map(value => ({ value, sort: Math.random() }))
|
|
.sort((a, b) => a.sort - b.sort)
|
|
.map(({ value }) => value);
|
|
}
|
|
|
|
add_task(async function test_negotiateLangPacks() {
|
|
const negotiations = [
|
|
{
|
|
// Exact match found.
|
|
systemLocale: "en-US",
|
|
availableLangPacks: ["en", "en-US", "zh", "zh-CN", "zh-Hans-CN"],
|
|
expectedLangPack: "en-US",
|
|
expectedDisplayName: "English (US)",
|
|
},
|
|
{
|
|
// Region-less match.
|
|
systemLocale: "en-CA",
|
|
availableLangPacks: ["en", "en-US", "zh", "zh-CN", "zh-Hans-CN"],
|
|
expectedLangPack: "en",
|
|
expectedDisplayName: "English",
|
|
},
|
|
{
|
|
// Fallback to a different region.
|
|
systemLocale: "en-CA",
|
|
availableLangPacks: ["en-US", "zh", "zh-CN", "zh-Hans-CN"],
|
|
expectedLangPack: "en-US",
|
|
expectedDisplayName: "English (US)",
|
|
},
|
|
{
|
|
// Match with a script. zh-Hans-CN is the locale used with simplified
|
|
// Chinese scripts, while zh-CN uses the Latin script.
|
|
systemLocale: "zh-Hans-CN",
|
|
availableLangPacks: ["en", "en-US", "zh", "zh-CN", "zh-TW", "zh-Hans-CN"],
|
|
expectedLangPack: "zh-Hans-CN",
|
|
expectedDisplayName: "Chinese (Hans, China)",
|
|
},
|
|
{
|
|
// Match excluding script but matching region. zh-Hant-TW should
|
|
// match zh-TW before zh-CN.
|
|
systemLocale: "zh-Hant-TW",
|
|
availableLangPacks: ["en", "zh", "zh-CN", "zh-TW"],
|
|
expectedLangPack: "zh-TW",
|
|
expectedDisplayName: "正體中文",
|
|
},
|
|
{
|
|
// No reasonable match could be found.
|
|
systemLocale: "tlh", // Klingon
|
|
availableLangPacks: ["en", "en-US", "zh", "zh-CN", "zh-Hans-CN"],
|
|
expectedLangPack: null,
|
|
expectedDisplayName: null,
|
|
},
|
|
{
|
|
// Weird, but valid locale identifiers.
|
|
systemLocale: "en-US-u-hc-h23-ca-islamic-civil-ss-true",
|
|
availableLangPacks: ["en", "en-US", "zh", "zh-CN", "zh-Hans-CN"],
|
|
expectedLangPack: "en-US",
|
|
expectedDisplayName: "English (US)",
|
|
},
|
|
{
|
|
// Invalid system locale
|
|
systemLocale: "Not valid",
|
|
availableLangPacks: ["en", "en-US", "zh", "zh-CN", "zh-Hans-CN"],
|
|
expectedLangPack: null,
|
|
expectedDisplayName: null,
|
|
},
|
|
];
|
|
|
|
for (const {
|
|
systemLocale,
|
|
availableLangPacks,
|
|
expectedLangPack,
|
|
expectedDisplayName,
|
|
} of negotiations) {
|
|
sandbox.restore();
|
|
const { resolveLangPacks } = mockAddonAndLocaleAPIs({
|
|
sandbox,
|
|
systemLocale,
|
|
});
|
|
|
|
const promise = LangPackMatcher.negotiateLangPackForLanguageMismatch();
|
|
// Shuffle the order to ensure that this test doesn't require on ordering of the
|
|
// langpack responses.
|
|
resolveLangPacks(shuffle(availableLangPacks));
|
|
const { langPack, langPackDisplayName } = await promise;
|
|
equal(
|
|
langPack?.target_locale,
|
|
expectedLangPack,
|
|
`Resolve the systemLocale "${systemLocale}" with available langpacks: ${JSON.stringify(
|
|
availableLangPacks
|
|
)}`
|
|
);
|
|
equal(
|
|
langPackDisplayName,
|
|
expectedDisplayName,
|
|
"The display name matches."
|
|
);
|
|
}
|
|
});
|
|
|
|
add_task(async function test_ensureLangPackInstalled() {
|
|
sandbox.restore();
|
|
const { resolveLangPacks, resolveInstaller } = mockAddonAndLocaleAPIs({
|
|
sandbox,
|
|
systemLocale: "es-ES",
|
|
appLocale: "en-US",
|
|
});
|
|
|
|
const negotiatePromise =
|
|
LangPackMatcher.negotiateLangPackForLanguageMismatch();
|
|
resolveLangPacks(["es-ES"]);
|
|
const { langPack } = await negotiatePromise;
|
|
|
|
const installPromise1 = LangPackMatcher.ensureLangPackInstalled(langPack);
|
|
const installPromise2 = LangPackMatcher.ensureLangPackInstalled(langPack);
|
|
|
|
resolveInstaller(["fake langpack"]);
|
|
|
|
info("Ensure both installers resolve when called twice in a row.");
|
|
await installPromise1;
|
|
await installPromise2;
|
|
ok(true, "Both were called.");
|
|
});
|