Skip to content
This repository has been archived by the owner on May 19, 2022. It is now read-only.

Commit

Permalink
Merge pull request #85 from rumbcam/feature/i18nextComponentBugFixes
Browse files Browse the repository at this point in the history
Feature/i18next component bug fixes
  • Loading branch information
claudiocro authored Jan 30, 2020
2 parents f454fc2 + 8dcd465 commit 63b3b3c
Show file tree
Hide file tree
Showing 5 changed files with 91 additions and 17 deletions.
8 changes: 5 additions & 3 deletions src/component.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,20 @@ export default {
},
render(h, { props, data, children, parent }) {
const i18next = parent.$i18n;
if (!i18next) {
const $t = parent.$t.bind(parent);
if (!i18next || !$t) {
return h(props.tag, data, children);
}

const { path } = props;
const options = props.options || {};

const REGEXP = i18next.i18next.services.interpolator.regexp;
const format = i18next.t(path, {
const i18nextOptions = {
...options,
interpolation: { prefix: '#$?', suffix: '?$#' }
});
};
const format = $t(path, i18nextOptions);
const tchildren = [];

format.split(REGEXP).reduce((memo, match, index) => {
Expand Down
12 changes: 7 additions & 5 deletions src/install.js
Original file line number Diff line number Diff line change
Expand Up @@ -126,11 +126,13 @@ export function install(_Vue) {
});

// extend Vue.js
Object.defineProperty(Vue.prototype, '$i18n', {
get() {
return this._i18n;
}
});
if (!Object.prototype.hasOwnProperty.call(Vue.prototype, '$i18n')) {
Object.defineProperty(Vue.prototype, '$i18n', {
get() {
return this._i18n;
}
});
}

Vue.prototype.$t = function t(key, options) {
return this._getI18nKey(key, options);
Expand Down
11 changes: 11 additions & 0 deletions test/unit/basic.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,15 @@ describe('basic', () => {
expect(duckMixin).to.be.false;
});
});
describe('if $i18n is already defined', () => {
it('should still install just fine', () => {
// If there are two instances of VueI18Next such as using a library that is using VueI18Next
// while the base project also uses VueI18Next then when the plugin tries to install VueI18Next
// it's VueI18Next.install.installed will be false as it should be and when it gets to
// where it should define $i18n on Vue's prototype can't because it's already defined and that is fine
VueI18Next.install.installed = false;
VueI18Next.install(Vue);
expect(VueI18Next.install.installed).to.be.true;
});
});
});
43 changes: 42 additions & 1 deletion test/unit/component.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,10 @@ describe('Components with backend', () => {
i18nOptions: { namespaces: 'common' },

render(h) {
return h('div', {}, [h('p', { ref: 'hello' }, [this.$t('key1')])]);
return h('div', {}, [
h('p', { ref: 'hello' }, [this.$t('key1')]),
h('i18next', { ref: 'i18nextComponent', props: {path: 'key1'} }, []),
]);
},
}).$mount(el);

Expand All @@ -305,11 +308,14 @@ describe('Components with backend', () => {

it('should render sub components correctly', async () => {
const root = vm.$refs.hello;
const i18nextComponent = vm.$refs.i18nextComponent;
expect(root.textContent).to.equal('key1');
expect(i18nextComponent.textContent).to.equal('key1');
backend.flush();
await nextTick();

expect(root.textContent).to.equal('dev__common__test');
expect(i18nextComponent.textContent).to.equal('dev__common__test');
});

it('should wait for translation to be ready', async () => {
Expand Down Expand Up @@ -380,4 +386,39 @@ describe('Components with backend', () => {
expect(key12.textContent).to.equal('de__common__test');
});
});

describe('when using i18next component and not $t', () => {
const i18next1 = i18next.createInstance();
let vueI18Next;
let vm;
beforeEach((done) => {
i18next1.use(backend).init({
lng: 'en',
});
vueI18Next = new VueI18Next(i18next1);

const el = document.createElement('div');
vm = new Vue({
i18n: vueI18Next,
i18nOptions: { namespaces: 'common' },

render(h) {
return h('div', {}, [
h('i18next', { ref: 'i18nextComponent', props: { path: 'key1' } }, []),
]);
},
}).$mount(el);

vm.$nextTick(done);
});

it('should render sub components correctly', async () => {
const root = vm.$refs.i18nextComponent;
expect(root.textContent).to.equal('key1');
backend.flush();
await nextTick();

expect(root.textContent).to.equal('dev__common__test');
});
});
});
34 changes: 26 additions & 8 deletions test/unit/directive.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -88,28 +88,46 @@ describe('directive', () => {
// const spy = sinon.spy(t);
const vm = new Vue({
i18n: vueI18Next,
data: { name: 'Hans' },
data: {
value: {
path: 'helloPerson',
language: 'de',
args: { name: 'Hans' },
},
},
// computed: {
// value() {
// return {
// path: this.path,
// language: this.language,
// args: this.args,
// };
// },
// },
render(h) {
return h('p', {
ref: 'text',
directives: [
{
name: 't',
rawName: 'v-t',
value: {
path: 'helloPerson',
language: 'de',
args: { name: this.name },
},
value: this.value,
expression:
"{ path: 'helloPerson', language: 'de', args: { name: this.name } }",
"{ path: 'helloPerson', language: 'de', args: { name: this.value.args.name } }",
},
],
});
},
}).$mount(el);

vm.name = 'Peter';
vm.value = {
path: 'helloPerson',
language: 'de',
args: { name: 'Peter' },
};
await nextTick();
expect(vm.$el.outerHTML).to.equal('<p>Hallo Peter</p>');
vm.value = null;
await nextTick();
expect(vm.$el.outerHTML).to.equal('<p>Hallo Peter</p>');
});
Expand Down

0 comments on commit 63b3b3c

Please sign in to comment.