Reading other issues, you seem to discourage ppl from using mixins, but they're so useful.
I would like to share some behavior between a bunch of components (especially across different builds, where "global" translations would still have to be duplicated)
const ChickenMixin = {
methods: {
scream () {
alert(this.$t('scream'))
}
},
i18n: {
messages: {
en: {
scream: 'cock-a-doodle-do'
},
fr: {
scream: 'cocorico'
}
}
}
}
it does not work at the moment : http://jsfiddle.net/2hs4pgwe/2/
It also should take in account when a component extends another.
const ComponentA = {
i18n: {
messages: {
en: {
'string1: 'String 1'
}
}
}
const ComponentB = {
i18n: {
messages: {
en: {
'string2: 'String 2'
}
}
}
const ComponentC = {
extends: ComponentA,
mixins: [
ComponentB
],
i18n: {
messages: {
en: {
'string3: 'String 3'
}
},
computed: {
string1() {
return this.$t('string1');
}
string2() {
return this.$t('string2');
}
string3() {
return this.$t('string3');
}
}
}
This is the expected behavior.
If this is ok, I can develop a Pull Request solving it.
According to how mixin works, it should work as @hanucito said.
By not changing the implementation of vue-i18n, adding the following code could work but i18n resources in mixins should be specified via __i18n array.
Vue.config.optionMergeStrategies.i18n = function (parentVal, childVal) {
return (childVal === undefined ? parentVal : childVal) || {};
};
Vue.config.optionMergeStrategies.__i18n = function (parentVal, childVal) {
const ret = [];
if (parentVal) {
ret.push(...parentVal);
}
if (childVal) {
ret.push(...childVal);
}
return ret;
};
The first part of i18n merging strategy is to make sure i18n object will always be created to merge resources from mixins.
The second part of i18n merging strategy is to merge the resources.
@yfwz100 I did not know about Vue.config.optionMergeStrategies. Thank you! I can workaround the issue with this for now, but it will nice to have this shipped with i18n, at least with a flag to disable or enable it.
I think adding a flag to enable mixin merging is a solution. Is there any plans for this feature? @kazupon
By not changing the implementation of vue-i18n, adding the following code could work but i18n resources in mixins should be specified via
__i18narray.Vue.config.optionMergeStrategies.i18n = function (parentVal, childVal) { return (childVal === undefined ? parentVal : childVal) || {}; }; Vue.config.optionMergeStrategies.__i18n = function (parentVal, childVal) { const ret = []; if (parentVal) { ret.push(...parentVal); } if (childVal) { ret.push(...childVal); } return ret; };The first part of i18n merging strategy is to make sure i18n object will always be created to merge resources from mixins.
The second part of i18n merging strategy is to merge the resources.
Hi @yfwz100
I don't know how to use your code (__i18n array ?). I have some errors...
Can you provide me an example (mixin and component using the mixin) please?
Any updates on this issue @kazupon? I stumbled across this issue and find this really annoying…
I would like this too, I have implemented the mergin strategy but through a lot of trial and error. And although it works, I'm not sure if it might not break for some combinations of i18n and __i18n and yaml loaders.
I had the same issue and found the solution using optionMergeStrategies a bit intrusive. I tried a few things and came up with this helper function which solved the problem:
export function mergeLocaleMessages(i18n, messages) {
for (const locale in messages) i18n.mergeLocaleMessage(locale, messages[locale])
}
You can simply use it within a beforeCreate hook by providing the $i18n plugin of the current Vue instance (a.k.a. this.$i18n). As you don't provide the i18n root instance, your translations will be scoped to the component which means you will still have component-based localization.
import { mergeLocaleMessages } from '@/helpers/i18n'
import i18nChicken from '@/locales/chicken.json'
const ChickenMixin = {
beforeCreate() {
mergeLocaleMessages(this.$i18n, i18nChicken)
},
methods: {
scream() {
alert(this.$t('scream'))
},
},
}
_@/locales/chicken.json_
{
"en": {
"scream": "cock-a-doodle-do"
},
"fr": {
"scream": "cocorico"
}
}
I personally like having my translations in separate files, but of course, you can define the object directly in your mixin. Hope it helps.
I wanted to share my merging strategy plugin that fixes an important bug when importing multiple mixins.
import Vue from 'vue'
Vue.config.optionMergeStrategies.i18n = function (parentVal, childVal) {
return (childVal === undefined ? parentVal : childVal) || {};
};
Vue.config.optionMergeStrategies.__i18n = function (parentVal, childVal) {
const ret = [];
if (parentVal) {
var stringed = parentVal.map(translation=>{
// check for when merging multiple mixins, the earlier mixins would get stringifyed multiple times
if(typeof translation === 'string')return translation
else {
return JSON.stringify(translation)
}
})
ret.push(...stringed);
}
if (childVal) {
ret.push(...childVal);
}
return ret;
};
Most helpful comment
I think adding a flag to enable mixin merging is a solution. Is there any plans for this feature? @kazupon