Bug 1762659 - Use MozIntl for stand-alone display names in LangPackMatcher.jsm; r=Mardak,nordzilla

Differential Revision: https://phabricator.services.mozilla.com/D142730
This commit is contained in:
Greg Tatum 2022-04-01 21:39:17 +00:00
Родитель b2c631dcf0
Коммит 852ecad7f2
5 изменённых файлов: 86 добавлений и 59 удалений

Просмотреть файл

@ -1157,20 +1157,15 @@ function useLanguageSwitcher(appAndSystemLocaleInfo, screens, screenIndex, setSc
}
(async () => {
const langPack = await window.AWNegotiateLangPackForLanguageMismatch(appAndSystemLocaleInfo);
const {
langPack,
langPackDisplayName
} = await window.AWNegotiateLangPackForLanguageMismatch(appAndSystemLocaleInfo);
if (langPack) {
// Convert the BCP 47 identifiers into the proper display names.
// e.g. "fr-CA" -> "Canadian French".
const appDN = new Intl.DisplayNames(appAndSystemLocaleInfo.appLocaleRaw, {
type: "language"
});
const langPackDN = new Intl.DisplayNames(langPack.target_locale, {
type: "language"
});
setNegotiatedLanguage({
langPackDisplayName: langPackDN.of(langPack.target_locale),
appDisplayName: appDN.of(appAndSystemLocaleInfo.appLocaleRaw),
langPackDisplayName,
appDisplayName: appAndSystemLocaleInfo.displayNames.appLanguage,
langPack,
requestSystemLocales: [langPack.target_locale, appAndSystemLocaleInfo.appLocaleRaw],
originalAppLocales: [appAndSystemLocaleInfo.appLocaleRaw]

Просмотреть файл

@ -36,23 +36,16 @@ export function useLanguageSwitcher(
}
(async () => {
const langPack = await window.AWNegotiateLangPackForLanguageMismatch(
const {
langPack,
langPackDisplayName,
} = await window.AWNegotiateLangPackForLanguageMismatch(
appAndSystemLocaleInfo
);
if (langPack) {
// Convert the BCP 47 identifiers into the proper display names.
// e.g. "fr-CA" -> "Canadian French".
const appDN = new Intl.DisplayNames(
appAndSystemLocaleInfo.appLocaleRaw,
{ type: "language" }
);
const langPackDN = new Intl.DisplayNames(langPack.target_locale, {
type: "language",
});
setNegotiatedLanguage({
langPackDisplayName: langPackDN.of(langPack.target_locale),
appDisplayName: appDN.of(appAndSystemLocaleInfo.appLocaleRaw),
langPackDisplayName,
appDisplayName: appAndSystemLocaleInfo.displayNames.appLanguage,
langPack,
requestSystemLocales: [
langPack.target_locale,

Просмотреть файл

@ -228,7 +228,7 @@ mr2-onboarding-start-browsing-button-label = Start browsing
## The following language names are generated by the browser's Intl.DisplayNames API.
##
## Variables:
## $negotiatedLanguage (String) - The name of the langpack's language, e.g. "European Spanish"
## $negotiatedLanguage (String) - The name of the langpack's language, e.g. "Español (ES)"
onboarding-live-language-header = Choose your language

Просмотреть файл

@ -23,13 +23,20 @@ if (Services.appinfo.processType !== Services.appinfo.PROCESS_TYPE_DEFAULT) {
* Attempts to find an appropriate langpack for a given language. The async function
* is infallible, but may not return a langpack.
*
* @returns {LangPack | null}
* @returns {{
* langPack: LangPack | null,
* langPackDisplayName: string | null
* }}
*/
async function negotiateLangPackForLanguageMismatch() {
const localeInfo = getAppAndSystemLocaleInfo();
const nullResult = {
langPack: null,
langPackDisplayName: null,
};
if (!localeInfo.systemLocale) {
// The system locale info was not valid.
return null;
return nullResult;
}
/**
@ -39,14 +46,14 @@ async function negotiateLangPackForLanguageMismatch() {
*/
const availableLangpacks = await mockable.getAvailableLangpacks();
if (!availableLangpacks) {
return null;
return nullResult;
}
/**
* Figure out a langpack to recommend.
* @type {LangPack | null}
*/
return (
const langPack =
// First look for a langpack that matches the baseName.
// e.g. system "fr-FR" matches langpack "fr-FR"
// system "en-GB" matches langpack "en-GB".
@ -65,8 +72,20 @@ async function negotiateLangPackForLanguageMismatch() {
availableLangpacks.find(({ target_locale }) =>
target_locale.startsWith(`${localeInfo.systemLocale.language}-`)
) ||
null
);
null;
if (!langPack) {
return nullResult;
}
return {
langPack,
langPackDisplayName: Services.intl.getLocaleDisplayNames(
undefined,
[langPack.target_locale],
{ preferNative: true }
)[0],
};
}
// If a langpack is being installed, allow blocking on that.
@ -278,10 +297,6 @@ function getAppAndSystemLocaleInfo() {
}
}
const displayNames = new Services.intl.DisplayNames(appLocaleRaw, {
type: "language",
});
// Live reloading with bidi switching may not be supported.
let canLiveReload = null;
if (systemLocale && appLocale) {
@ -295,7 +310,6 @@ function getAppAndSystemLocaleInfo() {
);
canLiveReload = systemDirection === appDirection || supportsBidiSwitching;
}
return {
// Return the Intl.Locale in a serializable form.
systemLocaleRaw,
@ -308,9 +322,17 @@ function getAppAndSystemLocaleInfo() {
// These can be used as Fluent message args.
displayNames: {
systemLanguage: systemLocale
? displayNames.of(systemLocale.baseName)
? Services.intl.getLocaleDisplayNames(
undefined,
[systemLocale.baseName],
{ preferNative: true }
)[0]
: null,
appLanguage: appLocale
? Services.intl.getLocaleDisplayNames(undefined, [appLocale.baseName], {
preferNative: true,
})[0]
: null,
appLanguage: appLocale ? displayNames.of(appLocale.baseName) : null,
},
};
}

Просмотреть файл

@ -35,8 +35,8 @@ add_task(function test_appLocaleLanguageMismatch() {
matchType: "language-mismatch",
canLiveReload: true,
displayNames: {
systemLanguage: "European Spanish",
appLanguage: "American English",
systemLanguage: "Español (ES)",
appLanguage: "English (US)",
},
});
});
@ -57,8 +57,8 @@ add_task(function test_appLocaleRegionMismatch() {
matchType: "region-mismatch",
canLiveReload: true,
displayNames: {
systemLanguage: "Canadian English",
appLanguage: "American English",
systemLanguage: "English (CA)",
appLanguage: "English (US)",
},
});
});
@ -80,8 +80,8 @@ add_task(function test_appLocaleScriptMismatch() {
matchType: "match",
canLiveReload: true,
displayNames: {
systemLanguage: "简体中文(中国)",
appLanguage: "中文(中国)",
systemLanguage: "Chinese (Hans, China)",
appLanguage: "简体中文",
},
});
});
@ -102,7 +102,7 @@ add_task(function test_appLocaleInvalidSystem() {
appLocale: { baseName: "en-US", language: "en", region: "US" },
matchType: "unknown",
canLiveReload: null,
displayNames: { systemLanguage: null, appLanguage: "American English" },
displayNames: { systemLanguage: null, appLanguage: "English (US)" },
});
});
@ -128,7 +128,7 @@ add_task(function test_bidiSwitchDisabled() {
canLiveReload: false,
displayNames: {
systemLanguage: "Arabic (Egypt)",
appLanguage: "American English",
appLanguage: "English (US)",
},
});
Services.prefs.clearUserPref("intl.multilingual.liveReloadBidirectional");
@ -153,7 +153,7 @@ add_task(async function test_bidiSwitchEnabled() {
canLiveReload: true,
displayNames: {
systemLanguage: "Arabic (Egypt)",
appLanguage: "American English",
appLanguage: "English (US)",
},
});
@ -173,48 +173,60 @@ add_task(async function test_negotiateLangPacks() {
// Exact match found.
systemLocale: "en-US",
availableLangPacks: ["en", "en-US", "zh", "zh-CN", "zh-Hans-CN"],
expected: "en-US",
expectedLangPack: "en-US",
expectedDisplayName: "English (US)",
},
{
// Region-less match.
systemLocale: "en-CA",
availableLangPacks: ["en", "en-US", "zh", "zh-CN", "zh-Hans-CN"],
expected: "en",
expectedLangPack: "en",
expectedDisplayName: "English",
},
{
// Fallback to a different region.
systemLocale: "en-CA",
availableLangPacks: ["en-US", "zh", "zh-CN", "zh-Hans-CN"],
expected: "en-US",
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-Hans-CN"],
expected: "zh-Hans-CN",
expectedLangPack: "zh-Hans-CN",
expectedDisplayName: "Chinese (Hans, China)",
},
{
// No reasonable match could be found.
systemLocale: "tlh", // Klingon
availableLangPacks: ["en", "en-US", "zh", "zh-CN", "zh-Hans-CN"],
expected: null,
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"],
expected: "en-US",
expectedLangPack: "en-US",
expectedDisplayName: "English (US)",
},
{
// Invalid system locale
systemLocale: "Not valid",
availableLangPacks: ["en", "en-US", "zh", "zh-CN", "zh-Hans-CN"],
expected: null,
expectedLangPack: null,
expectedDisplayName: null,
},
];
for (const { systemLocale, availableLangPacks, expected } of negotiations) {
for (const {
systemLocale,
availableLangPacks,
expectedLangPack,
expectedDisplayName,
} of negotiations) {
sandbox.restore();
const { resolveLangPacks } = mockAddonAndLocaleAPIs({
sandbox,
@ -225,14 +237,19 @@ add_task(async function test_negotiateLangPacks() {
// Shuffle the order to ensure that this test doesn't require on ordering of the
// langpack responses.
resolveLangPacks(shuffle(availableLangPacks));
const actual = (await promise)?.target_locale;
const { langPack, langPackDisplayName } = await promise;
equal(
actual,
expected,
langPack?.target_locale,
expectedLangPack,
`Resolve the systemLocale "${systemLocale}" with available langpacks: ${JSON.stringify(
availableLangPacks
)}`
);
equal(
langPackDisplayName,
expectedDisplayName,
"The display name matches."
);
}
});
@ -246,7 +263,7 @@ add_task(async function test_ensureLangPackInstalled() {
const negotiatePromise = LangPackMatcher.negotiateLangPackForLanguageMismatch();
resolveLangPacks(["es-ES"]);
const langPack = await negotiatePromise;
const { langPack } = await negotiatePromise;
const installPromise1 = LangPackMatcher.ensureLangPackInstalled(langPack);
const installPromise2 = LangPackMatcher.ensureLangPackInstalled(langPack);