Hello,
Personally, I'm not a big fan of declaring my translation strings via keywords (privacyPolicy in the following example), like so:
const messages = {
en: {
privacyPolicy: 'Privacy Policy'
},
de: {
privacyPolicy: 'Datenschutzerkl盲rung'
}
}
I normally split the messages up into language files and then use the English version as keys, whenever it makes sense:
export default {
'Privacy Policy': 'Datenschutzerkl盲rung'
}
This comes with a couple benefits. First, a translator won't have to search around for the actual string to translate and secondly, it allows me to write code like the following example, kinda like gettext. To me, this is cleaner, cause I know exactly what's going on:
<a href="/privacy-policy">{{ $t('Privacy Policy') }}</a>
The only issue I have with this approach is that I still need to maintain an English translation file cause when the key is used as a fallback, no substitutions are done:
<p>{{ $t('Hello {user}', { user: 'Bruce Banner' }) }}</p>
The above only works with an English translation file like so, which seems kinda silly:
export default {
'Hello {user}': 'Hello {user}'
}
It'd be great if there was a solution to this issue, maybe a constructor option to parse fallback keys. It's not a big deal really, but it does mess with my OCD tendencies a bit ;)
I solved it differently, actually. I use the English lang file as a translation template with empty values now. When initialising vue-i18n I then copy the keys across to the values for the English strings.
Another solution, if you don't want to manage empty translations file, could be to overwrite the missing handler (although you trade off some performance):
export const i18n = new VueI18n({
...
missing: (locale, key, vm) => {
var messages = i18n.getLocaleMessage(locale);
messages[key] = key;
i18n.setLocaleMessage(locale, messages);
},
});
Update
Another "hacky" solution that doesn't not cause rerendering like the missing handler is to extend the internal _translate method and populate the source language messages before returning the end result, eg:
const sourceMessages = {};
const originalTranslate = VueI18n.prototype._translate;
VueI18n.prototype._translate = function (messages, locale, fallback, key, host, interpolateMode, args) {
if (!sourceMessages[key]) {
sourceMessages[key] = key;
}
return originalTranslate.apply(this, arguments);
};
export var i18n = new VueI18n({
locale: 'en-US',
fallbackLocale: 'en-US',
messages: {'en-US': sourceMessages},
});
Most helpful comment
I solved it differently, actually. I use the English lang file as a translation template with empty values now. When initialising vue-i18n I then copy the keys across to the values for the English strings.