2.4.2 & 7.0.5 (using dist from master in fiddle)
Minimal example http://jsfiddle.net/Ly55ew8m/2/
Our use case is not represented in that fiddle, see below.
Passing a VueI18n instance to Vue.extend is ignored, only a plain old i18n options object works.
In fiddle just comment and un-comment the relevant lines
If a class instance would work, we could keep (and export) a reference to the instance and import it in other parts of the application (like vuex actions) to control vue-i18n, i.e. locale switch.
We can not use a class instance so we have to add the locale switch logic inside the Vue.extend options: i.e. watch a vuex getter for current language and switch language through this.$i18n.locale.
Thank you for your feedback!
This issue is occurred due to Vue.extend.
I seem that Vue.extend can not pass the Class instance. 馃
It does have an impact on Unit Testing for this kind of implementation:
https://vuejs.org/v2/guide/unit-testing.html#Writing-Testable-Components
We are developing a project that now uses vue-i18n. When we implemented it, some warnings appeared on existing tests:
WARN: '[vue-i18n] Cannot translate the value of keypath 'input.required'. Use the value of keypath as default.'
It correctly does any assertion, since the keypath will be compared with it own value and we are not testing the vue-i18n messages itself, but the values that the component uses for internal processing.
Is there any workaround to not triggering these warnings?
@kimuraz to get around this issue you must pass the i18n object into the constructor not the extend call.
const Constructor = Vue.extend(SmallComponent);
const vm = new Constructor({i18n}).$mount()
@rikbrowning Thank you, I'll give it a try to test it, although I've already solve it mocking vue-i18n instance using vue-test-utils + jest (changed my test tools) :)
@kimuraz do you have an example repo of your mocked vue-i18n instance via jest?
close (avoid with https://github.com/kazupon/vue-i18n/issues/200#issuecomment-359516610)
Hmmm, actually there are some use cases other than tests that would be covered by this.
For instance:
const CommonApplication = Vue.extend({
router: new VueRouter({
routes: [
{ path: '/shared', component: shared },
],
}),
i18n: new VueI18n({
locale: 'en',
messages: {
en: {
shared: 'Shared Message'
},
},
}),
});
const fooApplication = new CommonApplication({ el: '#foo' });
// Works as expected and $router contains /shared and /foo routes
fooApplication.$router.addRoutes([ { path: '/foo', component: foo } ]);
// Doesn't work and $i18n doesn't contain 'shared' message, but only 'foo'
fooApplication.$i18n.locale = 'en';
fooApplication.$i18n.mergeLocaleMessage('en', {
foo: 'Foo Message',
});
const barApplication = new CommonApplication({ el: '#bar' });
// Works as expected and $router contains /shared and /bar routes
barApplication.$router.addRoutes([ { path: '/bar', component: bar } ]);
// Doesn't work and $i18n doesn't contain 'shared' message, but only 'bar'
barApplication.$i18n.locale = 'en';
barApplication.$i18n.mergeLocaleMessage('en', {
bar: 'Bar Message',
});
@kazupon I've created this fiddle to illustrated the concept:
https://jsfiddle.net/vFragosop/rstygetw/9/
const Constructor = Vue.extend(SmallComponent);
const vm = new Constructor({i18n}).$mount()
In case it helps anyone else I had to also do
const i18n = this.$i18n
@kazupon I've found the reason why Vue.extend cannot work, It's because Vue.config.optionMergeStrategies.i18n use Vue.config.optionMergeStrategies.methods, which makes i18n instance loses his __proto__, so the options.i18n instanceof VueI18n becomes false. Will vue-i18n support Vue.extend({i18n})? If yes, I can fix this problem.
Most helpful comment
@kimuraz to get around this issue you must pass the i18n object into the constructor not the extend call.