vue-i18n
vue-i18n copied to clipboard
[feature request] Have $te check for fallback locales
Suppose I have the following messages and fallback config:
messages: {
en: {
message: {
hello: 'hello world',
greeting: 'good morning'
}
}
},
fallbackLocale: 'en'
And with my current $i18n.locale
set to "en-US"
, running $te
will have the following output:
this.$te('hello') // => false
Would it be a bad idea to configure the default behavior of $te
to take into account of the fallback locale setting?
So suppose I have the fallbackLocale
set to ['es-EC', 'en']
, and with $i18n.locale
set to "fr"
, running
this.$te('hello')
should be equivalent to
(this.$te('hello', 'fr') ||
this.$te('hello', 'es-EC') ||
this.$te('hello', 'es') ||
this.$te('hello', 'en'))
With that implemented, the current default behavior should still be reproduceable with this.$te('hello', this.$i18n.locale)
.
Could you add more detail about use cases for this enhancement ?
This has come up for me with enumerated values, where a property may have one of a limited number of values. Each known value is translated in the fallback locale, but I also want the behavior to be well defined if the value isn't known. For example, for data like this:
[
{
"type": "image",
"name": "My Image.png"
},
{
"type": "file",
"name": "My Data.csv"
}
]
and translations like this:
{
"en": {
"type": {
"image": "Image",
"file": "Data File"
}
},
"cs": {
"type": {
"image": "Obrázek"
}
}
}
I want to implement the following behavior:
- If there is a translation for the type in the current locale, display that.
- Otherwise, if there is a translation for the type in the fallback locale, display that.
- Otherwise (if the type isn't known), simply display the type.
Right now I've implemented:
const path = `type.${type}`;
return this.$te(path, this.$i18n.fallbackLocale) ? this.$t(path) : type;
It wouldn't work to use this.$te()
without specifying the fallback locale, because then if a translation is missing for the current locale, it won't fall back to the fallback locale. With fallback, the line would be a little simpler:
return this.$te(path) ? this.$t(path) : type;
It isn't hard to specify the fallback locale, but I didn't notice that it was necessary at first. $t()
and $tc()
both fall back to the fallback locale, so I assumed that $te()
would as well, and I was surprised when it didn't.
I am having a similar issue concerning the implicit locale fallback.
const i18n = new VueI18n({
locale: 'en-US',
messages: {
en: {
hello: 'hello world'
}
}
});
const key = 'hello';
console.log(i18n.t(key)); // hello world
console.log(i18n.te(key)); // false
// Workaround
console.log(i18n.t(key) !== key); // true
Because of the implicit fallback i18n.t
will return the en
localization for the en-US
locale. In my opinion i18n.te
should use the same implicit fallback logic as i18n.t
, but it does not, resulting in i18n.te('hello')
returning false
in the example above.
As a workaround, because I know that i18n.t
will return the passed key if it does not find any suitable localization, I check if the translation equals its key.
I've implemented something like this by extending the VueI18n class. It only handles the case where you do want it to check the fallback chain, not for when you want the old behavior.
class CustomVueI18n extends VueI18n {
constructor(props) {
super(props);
}
_te(key, locale, messages, ...args) {
const chain = this._getLocaleChain(locale, this.fallbackLocale);
return chain.some((lang) => super._te(key, lang, messages, ...args));
}
}
Hello, any update on this? We've solved the issue by extending the VueI18n class ass suggested above but having $te
check for any available translation key instead of just one translation key specific to the current locale sounds pretty interesting. Maybe even add an option to include fallback locales in the check or not?