Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
148 changes: 148 additions & 0 deletions proposals/i18n-get-available-languages.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
# Proposal: `i18n.getAvailableLanguages()`

**Summary**

An API which allows extensions to get a list of BCP47 language tags containing
the languages the browser can use and the extension provides resource files for.

**Document Metadata**

**Author:** carlosjeurissen

**Sponsoring Browser:** TBD

**Contributors:** hanguokai

**Created:** 2025-01-23

**Related Issues:** https://github.com/w3c/webextensions/issues/995, https://github.com/w3c/webextensions/issues/258, https://github.com/w3c/webextensions/issues/274

## Motivation

### Objective

Currently extensions can not easily get a list of supported languages without
hardcoding them first or need to rely on fetch try and error.

#### Use Cases

Allow to list the languages for extension settings language pickers.

Use the list of supported languages to match a specific website when applying
a content script.

Have this list independent of distribution (As some extension stores disallow
certain language tags).

Allow third parties to create polyfills for `i18n.withLanguage()` and
`i18n.setLanguage()`.

### Known Consumers

Extensions who currently have to maintain a manually currated list of supported
languages to offer content script language matching and/or allowing to change
Comment thread
carlosjeurissen marked this conversation as resolved.
the extension language in the extension settings.

An example of content-script matching is "Category Tabs for Google Keep", which
needs to match it's language with the page in question to properly integrate.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you show an example of how the API would be used in practice for this use case?

I'm wondering what a browser-defined API can provide that is not already possible by the extension. I'd expect that the extension can pre-generate a list of supported languages in relation to the files output to _locales/, which would be far more efficient than what a browser can offer.

You have already mentioned this possibility in the "Existing Workarounds", so it is clear that you are aware of the possibility.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated the proposal to include the practical example.

The browser-defined API would allow to list the intersection of languages the browser recognises and the extension includes. As mentioned, the set of resource files can be different depending on the extension store.

For Naver Whale specifically, I have a build script which removes unsupported resource files from the extension package after being built. There are even custom scenarios in which too many resource files requires the removal of the majority of resource files. In these scenarios, updating the set of supported languages in some JS file would add another layer of already complex build setup.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar to Rob, I'm not convinced that there are use cases which justify the addition of this API.

Adding a build step which exposes the bundled languages to your extension at runtime seems reasonable to me. The API would not provide anything which you could not also achieve in this way.

I can see value if we add the ability to set your extension's locale programatically. At that point, it is useful to know which of your locale directories the browser has parsed. However, it would make sense to add both APIs at the same time (as we discussed in #641), instead of just adding this API in isolation.

Copy link
Copy Markdown
Contributor Author

@carlosjeurissen carlosjeurissen Jan 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@oliverdunk thanks for taking a look at the proposal!

First of all, #641 has been stalled for more than a year and has not seen any progress since. Other APIs like the proposed i18n.withLanguage() would go well with i18n.getAvailableLanguages(). Having i18n.getAvailableLanguages() stuck in the i18n.setLanguage() proposal could block it's usage for i18n.withLanguage().

There are many reasons this API is useful in isolation even before i18n.withLanguage() and i18n.setLanguage() are available. besides the build step complexity listed above and the extension store compatibility. There is also the use case of being able to polyfill i18n.withLanguage() and i18n.setLanguage(). With i18n.getAvailableLanguages() one would be able to have a third party dependency polyfilling these potential future APIs. Thus especially now when i18n.withLanguage() and i18n.setLanguage() are not available, i18n.getAvailableLanguages() would unlock these use cases.


A simple naive implementation would be:
```js
const [pageLanguage, supportedLanguages] = await Promise.all([
tabs.detectLanguage(),
i18n.getAvailableLanguages(),
]);
const resourceLanguage = supportedLanguages.includes(pageLanguage);
const resourceFile = chrome.runtime.getURL(`_locales/${resourceLanguage}/messages.json`);
const messages = await fetch(resourceFile);
```

Future consumers of future related APIs like the `i18n.withLanguage()` and
`i18n.setLanguage()` APIs.

## Specification

### Schema

```typescript
namespace i18n {
function getAvailableLanguages(): Promise<string[]>;
}
```

This API should also be exposed in content scripts.

### Behavior

Given an extension with the following resource files:
`_locales/en/messages.json`, `_locales/es/messages.json` and
`_locales/es_419/messages.json`.

The `i18n.getAvailableLanguages()` method would return a promise which resolves
with the following array: `['en', 'es', 'es-419']`.

If no resource files are specified, and/or `default_locale` in the manifest is
missing, the promise will reject with an error stating extension localisation
is required for this method to work properly.

Comment thread
carlosjeurissen marked this conversation as resolved.
If a browser is unable to offer a specific language tag in `i18n.withLanguage()`
or `i18n.setLanguage()`, for example, because it does not understand the tag
(think about `_locales/n/messages.json`), or if a directory has no messages.json
file, it should not include said language tag. This does not mean a browser
should only return languages the browser UI itself supports. An extension could
offer additional languages outside the set of languages used for its own browser
UI. In that case browsers can offer support for these languages and preferably
should support and return them.

### New Permissions

No new permissions are needed.

### Manifest File Changes

No manifest file changes are required.

## Security and Privacy

### Exposed Sensitive Data

The returned information could in theory already be known to the extension. This
information is not sensitive.

### Abuse Mitigations

As this does not expose sensitive data, there is no abuse potential.

### Additional Security Considerations

Exposing the list of locales an extension has resource files for is unlikely to
introduce any new security risks.

## Alternatives

### Existing Workarounds

Extensions could hard-code the supported locale tags. This is however error
prone as the list may be outdated. Some extensions may also reduce the list
of included resource files for compatibility with specific extension stores. See
https://forum.whale.naver.com/topic/39749/

### Open Web API

I18n resources are currently extension only. While there are talks about
open web dom localization (See https://github.com/mozilla/explainers/blob/main/dom-localization.md)
They are far from ready and their handling of resources will be different from
current web extensions.

## Implementation Notes

Since this information will not change during the lifecycle of an extension. It
can easily be cached on installation/update.

The locale tags need to be turned into a valid bcp47 tag. For example, for the
resource `_locales/en_US`, the bcp47 tag `en-US` should be returned.

## Future Work

Allow to use `i18n.getMessage` with a different language. See https://github.com/w3c/webextensions/issues/274
Allow to use change the language of extensions. See: https://github.com/w3c/webextensions/issues/258#issue-1344495962 and https://github.com/w3c/webextensions/pull/641
Loading