- 
                Notifications
    You must be signed in to change notification settings 
- Fork 71
Description
Update: In order to express it completely and clearly, I reorganized the proposal and edited it many times after 2022-09-12.
Summary
Currently, browser.i18n only display one default language to users. Users can't change the language to other extension supported languages independently. Developers need to use their own solutions to provide users with multiple language select menu.
It makes sense for an app to use another language independently of the operating system. For example, Android supports per-app language preferences (here is its docs and video). The same goes for extensions. This proposal brings per-app language preferences to browser extensions.
Tracking bugs: Chromium-1365283 , Firefox-1791356
Main Content
1. Browser built-in supply a language select menu per extension
Since this is a general purpose feature for all users and extensions, browser built-in support is best.
If browsers built-in support a language select menu per extensions, all developers, all existing extensions and users can get this benefit right away. Ideally, developers just use current i18n api without doing anything. Another benefit is that it's much easier for developers to test i18n.
2. New APIs for developers
/**
 * get the current language used by i18n.getMessage()
 * return the language tag,  e.g. en-US, zh-CN.
 */
i18n.getCurrentLanguage() => code: String.
/**
 * set a new language used in this extension.
 * if code is null, revert to the default state(follow the browser UI language).
 * if code is not valid, reject it.
 * return a Promise, resolved when the operation is complete.
 */
i18n.setCurrentLanguage(code: String) => Promise<void>
/**
 * get all languages that supported by this extensions.
 * return a Promise, resolved with an array of language tags.
 */
i18n.getAllLanguages() => code_array: Promise<Array<String>>
/**
 * After i18n changed to a new language, the browser triggers a language changed event.
 * callback is (new_language_code: String) => void
 */
i18n.onLanguageChanged.addListener(callback)
Ideally, developers just use current i18n api without doing anything if there is a browser-supplied language select menu. The new api is only used to integrate this feature with the developer-supplied language select menu. For example, in the extension's options page, developers use get/setCurrentLanguage and getAllLanguages to create a language select menu for users.
i18n.setCurrentLanguage(code) is persistent. It is a setting per extensions which saved by browsers. If the extension remove a language in the new version and current language is that, then browser fall back to the default language.
code is standard language code, like 'en-US', not 'en_US'(folder name).
How to get language display names? Use Intl.DisplayNames, for example:
const currentLanguage = i18n.getCurrentLanguage();
const displayName = new Intl.DisplayNames([currentLanguage], 
      { type: 'language' , languageDisplay: 'standard' });
const allLanguages = await i18n.getAllLanguages();
for (let code of allLanguages) {
    let name = displayName.of(code)); // language display name for code
    // use code and name to create a language select
}
After changing the language, the browser triggers a onLanguageChanged event. This event is useful for updating UI for already opened extension pages and other UI parts like badgeText, badgeTitle and context menu.
i18n.onLanguageChanged.addListener(function(newCode) {
    // update extension page
    button.textContent = i18n.getMessage(buttonLabel);
    // update extension UI parts
    action.setTitle({title: i18n.getMessage(title)});
    action.setBadgeText({text: i18n.getMessage(text)});
    contextMenus.update(...);
});
3. Another New API (optional for implementation)
i18n.getMessage(messageName, substitutions?,  {language: "langCode"})
At present, i18n.getMessage() doesn't allow specifying a different language. I suggest add a new property to specify a language in the options parameter(the 3rd parameter which already support a "escapeLt" property). Maybe it is useful for some developers or some use cases.
Related References
https://developer.chrome.com/docs/extensions/reference/i18n/
https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/i18n
https://crbug.com/660704
#252
