Open cupcakearmy opened 1 year ago
Hey @cupcakearmy 👋
The issue is that right now this logic is not exposed and needs to be handled by the developer by iterating the available languages, creating subsets (en, en-US, etc.) and then match them agains the $locales available in the lib.
Not sure I'm following 100% 😅 Can you exemplify why you need this logic in the app?
Sure!
So immagine a site X
has localised content for ['en', 'de', 'es']
. A user Y
has it's browser/os setup with italian as first and spanish as second languge. this resulst in accept-language
and window.navigator.languages
to have a content similar to it,es
.
Currently, as the lib only supports one language, the webpage would try to load locales for it
, not finding them and falling back to en
. However in theory they would have had es
in common.
So we need to write additional code to handle this behavior.
Hope this clears up the confusion :)
Got it, thanks! Changing the $locale
store to an array would be a breaking change and I would say that users would usually expect it to return the current locale being used. That said, nothing prevents us from making it accept an array as input.
$locale = navigator.languages
or locale.set(['en', 'de', 'es'])
=> would resolve to es
It may be a bit weird to assign it to an array and have a string
as the actual value though 🤔
Yes, would not enforce it as array, only as an accepted value, as it's not the most common use case. Maybe one could add a currentLocale
store? Up to you :)
Maybe one could add a currentLocale store? Up to you :)
Thought about it too. Would still be a breaking change, though 😅
Yes, would not enforce it as array
I meant accepting an array as an input, but the output would always be a single string. However, while I was typing this I thought that maybe typing a store in such a way is not possible 🙈
Anyway, my point is that it seems the "array" is only useful as an input to define the initial locale, correct? I wouldn't want to complicate the usage of the $locale
in all the other places it may be used just because of it. I will sit on this for a bit, but suggestions and feedbacks are always welcome 🙏
We could change how we recommend changing the locale. Right now, one should modify the $locale
store directly. We could keep this but introduce a setLocale
or changeLocale
function that would be the one that accepted both string and an array of strings.
I agree on every point :)
It's def. an initialization thing. So a helper function would be also enough, to choose the most approriate locale, and leave the whole $locale
untouched, which is def. a good thing :)
I think it might be possible with proxies, but yes, introduces unecessary "magic"
I'm still exploring modifying the $locale.set
approach. One limitation though is that to know what locale to use from an array, the consumer must have already registered/added messages to the dictionary:
Using your example, given that there are messages registered for these three languages, we can decide which one to "set" as the $locale
value based on them.
init({
fallbackLocale: 'en',
});
register('en', () => Promise.resolve({ foo: 'Foo' }));
register('de', () => Promise.resolve({ foo: 'Foo' }));
register('es', () => Promise.resolve({ foo: 'Foo' }));
expect(get($locale)).toBe('en');
await $locale.set(['it', 'es']);
expect(get($locale)).toBe('es');
What should happen with the value of $locale
if the locales passed in the array are not available? Should it fallback to the fallbackLocale
? The current behaviour would be to leave the $locale
store value as undefined
.
I'm inclined to leave it as undefined
and the rest of the work to the already existing logic for fallbacking to the fallbackLocale
when formatting a message
I've released an alpha version 3.5.0-alpha.0
and this is the PR. I can't test this within the scope of Svelte right now though
I may have missed this in the tread, but what about the fallbackLocale as an Object or Array instead? vue-i18n has something like this:
fallbackLocale: {
'en-ie': ['en-gb'],
pap: ['nl'],
es: ['en-gb'],
ase: ['en-us'],
fcs: ['fr-ca'],
lsb: ['fr'],
'pt-br': ['pt', 'es'],
no: ['en-us'],
default: ['en-us', 'en']
}
I have to support many languages and having a graceful fallback can be helpful. Of course the example above is complex but gives the idea of a cascade type fallback hierarchy. For each locale, an array of locales can be set as a fallback with (in this case) English as a last resort.
Is your feature request related to a problem? Please describe.
This lib has the notion of a single locale store. From there possible variations are extrapolated.
https://github.com/kaisermann/svelte-i18n/blob/0516bb417c4d510e5cd5d225b60cb6ad469118a5/src/runtime/stores/dictionary.ts#L36
However in the real world both the
Accept-Language
headers andnavigator.languages
expose multiple languages, in order of user preference. This is a very useful feature as they can be used as a fallback if a specific is not available, before falling back to the globalfallbackLocale
The issue is that right now this logic is not exposed and needs to be handled by the developer by iterating the available languages, creating subsets (
en
,en-US
, etc.) and then match them agains the$locales
available in the lib.Describe the solution you'd like
Since the language matching feature is already in the codabase and does basically that one could:
$locale
store to also, beside a string, give a list of strings.Personally I'd say options 2 is the way to go
Describe alternatives you've considered
Write the logic in every project, for every dev. def. duable but it's a pity as most of the logic, as stated above, is alrady in the lib.
How important is this feature to you?
Not dealbreaking but it would def. be a welcome addition.
Additional context