Skip to content

Commit 794b2bb

Browse files
authored
feat: Support useI18n for Legacy API mode (#940)
* feat: Support useI18n for Legacy API mode * remove comments * fix: reduce build size with feature flag * fix: add e2e tests
1 parent dec3f64 commit 794b2bb

File tree

6 files changed

+946
-32
lines changed

6 files changed

+946
-32
lines changed

e2e/composition.test.js

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
;['legacy'].forEach(pattern => {
2+
describe(`${pattern}`, () => {
3+
beforeAll(async () => {
4+
await page.goto(
5+
`http://localhost:8080/examples/${pattern}/composition.html`
6+
)
7+
})
8+
9+
test('initial rendering', async () => {
10+
await expect(page).toMatchElement('#app p', {
11+
text: 'こんにちは、世界!'
12+
})
13+
await expect(page).toMatchElement('#app div.child p', {
14+
text: 'やあ!'
15+
})
16+
})
17+
18+
test('change locale', async () => {
19+
// root
20+
await expect(page).toSelect('#app select', 'en')
21+
await expect(page).toMatchElement('#app p', { text: 'hello world!' })
22+
await expect(page).toMatchElement('#app div.child p', {
23+
text: 'Hi there!'
24+
})
25+
26+
// Child
27+
await expect(page).toSelect('#app div.child select', 'ja')
28+
await expect(page).toMatchElement('#app p', { text: 'hello world!' })
29+
await expect(page).toMatchElement('#app div.child p', {
30+
text: 'やあ!'
31+
})
32+
})
33+
})
34+
})

examples/legacy/composition.html

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<meta charset="utf-8" />
5+
<title>Allow Composition API on legacy example</title>
6+
<script src="../../node_modules/vue/dist/vue.global.js"></script>
7+
<script src="../../packages/vue-i18n/dist/vue-i18n.global.js"></script>
8+
</head>
9+
<body>
10+
<div id="app">
11+
<h1>Root</h1>
12+
<form>
13+
<label for="locale-select">{{ $t('message.language') }}</label>
14+
<select id="locale-select" v-model="$i18n.locale">
15+
<option value="en">en</option>
16+
<option value="ja">ja</option>
17+
</select>
18+
</form>
19+
<p>{{ $t("message.hello") }}</p>
20+
<Child />
21+
</div>
22+
<script>
23+
const { createApp } = Vue
24+
const { createI18n, useI18n } = VueI18n
25+
26+
const Child = {
27+
template: `
28+
<div class="child">
29+
<h1>Child</h1>
30+
<form>
31+
<label>{{ t('message.language') }}</label>
32+
<select v-model="locale">
33+
<option value="en">en</option>
34+
<option value="ja">ja</option>
35+
</select>
36+
</form>
37+
<p>{{ t('message.hi') }}</p>
38+
</div>
39+
`,
40+
setup() {
41+
const { t, locale } = useI18n({
42+
useScope: 'local',
43+
locale: 'en',
44+
messages: {
45+
en: {
46+
message: {
47+
language: 'Language',
48+
hello: 'hello earth!',
49+
hi: 'Hi there!'
50+
}
51+
},
52+
ja: {
53+
message: {
54+
language: '言語',
55+
hello: 'こんにちは、地球!',
56+
hi: 'やあ!'
57+
}
58+
}
59+
}
60+
})
61+
62+
return { t, locale }
63+
},
64+
// you need to define `i18n` option with `setup`
65+
i18n: {}
66+
}
67+
68+
const i18n = createI18n({
69+
allowComposition: true,
70+
locale: 'ja',
71+
messages: {
72+
en: {
73+
message: {
74+
language: 'Language',
75+
hello: 'hello world!',
76+
hi: 'Hi !'
77+
}
78+
},
79+
ja: {
80+
message: {
81+
language: '言語',
82+
hello: 'こんにちは、世界!',
83+
hi: 'こんにちは!'
84+
}
85+
}
86+
}
87+
})
88+
89+
const app = createApp({
90+
components: { Child }
91+
})
92+
app.use(i18n)
93+
app.mount('#app')
94+
</script>
95+
</body>
96+
</html>

packages/vue-i18n-core/src/composer.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,8 @@ import type {
106106
import type { VueDevToolsEmitter } from '@intlify/vue-devtools'
107107
import { isLegacyVueI18n } from './utils'
108108

109+
export { DEFAULT_LOCALE } from '@intlify/core-base'
110+
109111
// extend VNode interface
110112
export const DEVTOOLS_META = '__INTLIFY_META__'
111113

packages/vue-i18n-core/src/errors.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ export const I18nErrorCodes = {
3232
NOT_COMPATIBLE_LEGACY_VUE_I18N: inc(), // 25
3333
// bridge support vue 2.x only
3434
BRIDGE_SUPPORT_VUE_2_ONLY: inc(), // 26
35+
// need to define `i18n` option in `allowComposition: true` and `useScope: 'local' at `useI18n``
36+
MUST_DEFINE_I18N_OPTION_IN_ALLOW_COMPOSITION: inc(), // 27
3537
// for enhancement
3638
__EXTEND_POINT__: inc() // 27
3739
} as const
@@ -65,5 +67,7 @@ export const errorMessages: { [code: number]: string } = {
6567
[I18nErrorCodes.NOT_COMPATIBLE_LEGACY_VUE_I18N]:
6668
'Not compatible legacy VueI18n.',
6769
[I18nErrorCodes.BRIDGE_SUPPORT_VUE_2_ONLY]:
68-
'vue-i18n-bridge support Vue 2.x only'
70+
'vue-i18n-bridge support Vue 2.x only',
71+
[I18nErrorCodes.MUST_DEFINE_I18N_OPTION_IN_ALLOW_COMPOSITION]:
72+
'Must define ‘i18n’ option in Composition API with using local scope in Legacy API mode'
6973
}

0 commit comments

Comments
 (0)