-
Notifications
You must be signed in to change notification settings - Fork 56
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Proposal: i18n.getLanguageDictionary
#274
Comments
What about |
@xeenon is true webExtensions currently mention "locale" here and there. This is something we can talk about as well. From most use cases I have seen, the getMessage API in browser extensions is mostly used for language and not locale. The region part of the language tag is mostly used to make the language more specific vs for region purposes. Especially now we have the Intl web API, taking care of most regional formatting use cases. This, and the fact most of the languages we currently handle in browserExtensions completely lack a regional suffix, would make me prefer language over locale not just for this API, but also in other areas of extensions. |
In abstract, I think Chrome is supportive of an end user's desire to change an extension's language independent of the browser UI or an extension developer's desire to show strings in multiple languages. That said, we're a bit hesitant with the As an alternative, what if we were to modify the signature of function getMessage(
messageName: string,
substitutions?: string|string[],
options?: {
escapeLt: boolean,
// New! Takes a locale string such as "pt-BR"
locale: string
},
): Promise<string> This approach may be more ergonomic for developers that wish to work with multiple languages while still allowing developers that wish to use the dictionary pattern to opt into it. function getLocaleDictionary(locale: string) {
return function(
messageName: string,
substitutions?: string|string[],
options?: { escapeLt: boolean }
) {
return browser.i18n.getMessage(messageName, substitutions, {...options, locale});
}
}
let getPtBrMessage = getLocaleDictionary("pt-BR");
let message = getPtBrMessage("example_message"); |
@dotproto This is the original proposal of #258 (see edited history -> oldest). Then it evolves into a more perfect proposal, and still keep the api that can specify language parameter for getMessage. |
At this point we appear to have broad alignment that this is a capability the platform should support. Next step is to align on an API design. We are open to proposals on how best to address this. |
@dotproto Do all browsers support #258 ? That is the same capability like this including |
#258 differs from this issue, in that it requests changing the default locale and/or UI to change the default locale. This ticket is a request for a way to access the message strings without changing defaults, and the API is asynchronous by design. That can be implemented reasonably without a large implementation burden in browsers. |
The issue with this one is that the API is synchronous. A straightforward way to solve that part of the API is to introduce another async method that initializes the translation for the given locale. |
There was a feature request like this proposal, and Chrome was not sure whether to implement it. Because it is trivial for developers to implement this proposal. e.g.
Implementation burden can always be used as a reason for any proposal. But don't forget that platforms exist to serve developers and users, especially for common needs. Please balance real user needs and browser implementation burden and developer implementation burden. |
It is not. Since this would not cover for substitutions and language fallbacks.
To make the API sync would mean the getMessage request would be blocking the main thread until the browser deals with preparing the langauge dictionary. If I recall correctly devlin suggested another approach which roughly would look like: browser.i18n.getLanguageDictionary('pt-BR').then((languageDictionary) => {
let someMessage = browser.i18n.getMessage('some_id', substitutions?, {
dictionary: languageDictionary,
});
}); This seems pretty verbose. Another solution would be to merge the above with your (@hanguokai ) syntax. In which you first have to initialise the specific language, after which you can use it sync. So you get: browser.i18n.initLanguage('pt-BR').then(() => {
let someMessage = browser.i18n.getMessage('some_id', substitutions?, {
language:'pt-BR',
});
}); If the language has not been initialised yet, the |
This part of the functionality can be encapsulated with a little extra code (I am currently using my own solution). Or use an independent I18N library as a solution as I said before. What I mean here is that this API can be easily implemented by developers themselves. Of course, it's always good if there is an official API. sync vs async? Why #258 is to change the default locale, so it is still the sync way to use |
Even tho I disagree on this. With the same logic this would be true for 258 as well.
In the case of content scripts it makes a lot of sense to match the language of the page and thus control the language separate from the general extension language.
Which would be great. I would love extension developers and potentially users to be able to modify the language used by an extension. I do not see how this proposal conflicts with #258 in any way. One does not exclude the other. As mentioned they cover different use cases. |
@hanguokai @rdcronin added the alternative proposals to the main comment. Let me know your thoughts. |
Of course, #258 can also be implemented by developers themselves, but there is more to do. You need to save the user's preferred language yourself, and read it first every time before
Maybe, but not necessarily. If I were a user, I would prefer it to be the language of the extension. For example, an extension that displays translated content of user selected-text on a page, its own UI should be the language of the extension.
They have some subtle intersections. But I agree that browsers can support both to cover different use cases. |
@rdcronin @carlosjeurissen |
Proposal AThe
Proposal B and CThey are similar. They both load a language first. It works. But:
Furthermore, I suggest it also accepts an array of languages, for example
Proposal DFrom a developer's perspective, this is the easiest to use. However, from an implementation perspective, browsers usually only cache a few languages: the default language (the "default_locale" in manifest file), the browser UI language and other fallback languages if possible. It is a bit difficult to have the browser load and cache all the languages. I have another proposal: Proposal E
This is similar to #258 . The difference is that #258 change the default language globally (all contexts) and persistently, but this proposal only change the language in the current context. For example, it doesn't affect another extension page. |
@xeenon agreed returning a @hanguokai Thanks for your feedback! Passing the method directly could be even more elegant indeed. Incorporated this and Proposal E in the main issue. As for accepting an Array, this could be done for any of the proposals. It reminds me of the yet unresolved discussion on how to deal with language fallbacks. See: #296 |
I chatted with @oliverdunk about this. My current thinking:
With all these in mind, I think I'd most lean towards Proposal D. It seems the easiest for developers and most ergonomic, and I think browsers and implement it in a way to have reasonable performance. @xeenon , WDYT? |
I would be happy with Proposal D and Proposal B (in that order). |
Proposal D was the exact same design I originally proposed in #258 and is an optional method in the final version of #258. The issue 274 was separated from the issue 258 because some people didn't accept it as a synchronous method at the time. As time goes by, if we finally decide to accept Proposal D, I can also add it as a supplement to #641. |
This has been discussed during TPAC 2024 and it was agreed Proposal B is the preferred by all browsers. Proposal A was rejected as it introduces new concepts new to the extensions platform. Proposal D was rejected as it's synchronous nature requires blocking the main process which could be troublesome. |
As requested by @Rob--W, splitting this proposal off from #258
Why
Proposal A
Introduce a
i18n.getLanguageDictionary
method. In which the first and only parameter is the language tag as string. Returning a promise with the languageDictionary allowing you to request messages from as follows:Or with async/await:
The name of this method can be worked on. Potential alternatives are
createLanguageInstance
andgetLanguageInstance
.A variant on this is directly passing the
getMessage
method as suggested by @hanguokai in #274 (comment) .Or with async/await:
Proposal B
Introduce a
i18n.getLanguageDictionary
method. In which the first and only parameter is the language tag as string. Returning a promise with the languageDictionary allowing you to request messages from as follows:Proposal C
Introduce an async
i18n.initLanguage
method. In which the first and only parameter is the language tag as string. This would initialise the messagedictionary on the background. The messages can then be fetched sync by passing the language parameter as option.Proposal D
Allow passing the requested language synchronously. Most convenient for developers however potentially tricky implementation-wise.
Proposal E
(from @hanguokai comment #274 (comment))
This is similar to #258 . The difference is that #258 change the default language globally (all contexts) and persistently, but this proposal only change the language in the current context. For example, it doesn't affect another extension page.
Edge cases
getMessage
method, it attempt to check for other available files. In the above example, it would first check pt-BR, then pt, then the default_locale (often english). Firefox skips the pt if the message is not present in pt-BR, yet is available in pt. We might want to raise a separate issue for this.The text was updated successfully, but these errors were encountered: