Skip to content

Commit 89de604

Browse files
authored
improvement: exporse type casting API for Legacy mode (#700)
related: #695
1 parent 666a043 commit 89de604

File tree

9 files changed

+118
-4
lines changed

9 files changed

+118
-4
lines changed

docs/guide/migration/ways.md

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ Include `vue-i18n-bridge` after `vue`, `@vue/composition-api` and it will instal
3939
<script src="https://cdn.jsdelivr.net/npm/[email protected]"></script>
4040
<script src="https://unpkg.com/vue-i18n@8/dist/vue-i18n.min.js"></script>
4141
<script src="https://cdn.jsdelivr.net/npm/@vue/[email protected]"></script>
42-
<script src="https://unpkg.com/[email protected].6/dist/vue-i18n-bridge.global.prod.js"></script>
42+
<script src="https://unpkg.com/[email protected].8/dist/vue-i18n-bridge.global.prod.js"></script>
4343
```
4444

4545
### Usage
@@ -119,6 +119,37 @@ const app = new Vue({ i18n })
119119
app.$mount('#app')
120120
```
121121

122+
for TypeScript:
123+
```ts
124+
import Vue from 'vue'
125+
import VueCompositionAPI from '@vue/composition-api'
126+
import { createI18n, useI18n, castToVueI18n } from 'vue-i18n-bridge'
127+
128+
Vue.use(VueCompositionAPI)
129+
Vue.use(VueI18n, { bridge: true })
130+
131+
const i18n = createI18n({
132+
locale: 'ja',
133+
messages: {
134+
en: {
135+
message: {
136+
hello: 'hello, {name}!'
137+
}
138+
},
139+
ja: {
140+
message: {
141+
hello: 'こんにちは、{name}!'
142+
}
143+
}
144+
}
145+
}, VueI18n)
146+
147+
Vue.use(i18n)
148+
149+
const app = new Vue({ i18n: castToVueI18n(i18n) }) // you need to cast `i18n` instance
150+
app.$mount('#app')
151+
```
152+
122153
### Usage UMD module in browser
123154

124155
```js

jest.config.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,9 @@ module.exports = {
9898
// A map from regular expressions to module names that allow to stub out resources with a single module
9999
moduleNameMapper: {
100100
'^@intlify/(.*?)$': '<rootDir>/packages/$1/src',
101-
'vue-i18n': '<rootDir>/packages/vue-i18n/src'
101+
'vue-i18n': '<rootDir>/packages/vue-i18n/src',
102+
'vue-i18n-bridge': '<rootDir>/packages/vue-i18n-bridge/src',
103+
'petite-vue-i18n': '<rootDir>/packages/petite-vue-i18n/src'
102104
},
103105

104106
// An array of regexp pattern strings, matched against all module paths before considered 'visible' to the module loader

packages/vue-i18n-bridge/README.md

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ Include `vue-i18n-bridge` after `vue`, `@vue/composition-api` and it will instal
3939
<script src="https://cdn.jsdelivr.net/npm/[email protected]"></script>
4040
<script src="https://unpkg.com/vue-i18n@8/dist/vue-i18n.min.js"></script>
4141
<script src="https://cdn.jsdelivr.net/npm/@vue/[email protected]"></script>
42-
<script src="https://unpkg.com/[email protected].5/dist/vue-i18n-bridge.global.prod.js"></script>
42+
<script src="https://unpkg.com/[email protected].8/dist/vue-i18n-bridge.global.prod.js"></script>
4343
```
4444

4545
## 🚀 Usage
@@ -119,6 +119,37 @@ const app = new Vue({ i18n })
119119
app.$mount('#app')
120120
```
121121

122+
For TypeScript:
123+
```ts
124+
import Vue from 'vue'
125+
import VueCompositionAPI from '@vue/composition-api'
126+
import { createI18n, useI18n, castToVueI18n } from 'vue-i18n-bridge'
127+
128+
Vue.use(VueCompositionAPI)
129+
Vue.use(VueI18n, { bridge: true })
130+
131+
const i18n = createI18n({
132+
locale: 'ja',
133+
messages: {
134+
en: {
135+
message: {
136+
hello: 'hello, {name}!'
137+
}
138+
},
139+
ja: {
140+
message: {
141+
hello: 'こんにちは、{name}!'
142+
}
143+
}
144+
}
145+
}, VueI18n)
146+
147+
Vue.use(i18n)
148+
149+
const app = new Vue({ i18n: castToVueI18n(i18n) }) // you need to cast `i18n` instance
150+
app.$mount('#app')
151+
```
152+
122153
### Usage UMD module in browser
123154

124155
```js

packages/vue-i18n-bridge/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ export {
8484
export {
8585
createI18n,
8686
useI18n,
87+
castToVueI18n,
8788
I18nInjectionKey,
8889
I18nOptions,
8990
I18nAdditionalOptions,

packages/vue-i18n-bridge/src/runtime.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ export {
7979
export {
8080
createI18n,
8181
useI18n,
82+
castToVueI18n,
8283
I18nInjectionKey,
8384
I18nOptions,
8485
I18nAdditionalOptions,

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

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -752,6 +752,29 @@ export function useI18n<
752752
>
753753
}
754754

755+
/**
756+
* Cast to VueI18n legacy compatible type
757+
*
758+
* @remarks
759+
* This API is provided only with [vue-i18n-bridge](https://vue-i18n.intlify.dev/guide/migration/ways.html#what-is-vue-i18n-bridge).
760+
*
761+
* The purpose of this function is to convert an {@link I18n} instance created with {@link createI18n | createI18n(legacy: true)} into a `[email protected]` compatible instance of `new VueI18n` in a TypeScript environment.
762+
*
763+
* @param i18n - An instance of {@link I18n}
764+
* @returns A i18n instance which is casted to {@link VueI18n} type
765+
*
766+
* @VueI18nTip
767+
* :new: provided by **vue-i18n-bridge only**
768+
*
769+
* @VueI18nGeneral
770+
*/
771+
export const castToVueI18n = /* #__PURE__*/ (i18n: I18n): VueI18n => {
772+
if (!isLegacyVueI18n(i18n)) {
773+
throw createI18nError(I18nErrorCodes.NOT_COMPATIBLE_LEGACY_VUE_I18N)
774+
}
775+
return i18n as unknown as VueI18n
776+
}
777+
755778
function createGlobal(
756779
options: I18nOptions,
757780
legacyMode: boolean,

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ export {
7070
export {
7171
createI18n,
7272
useI18n,
73+
castToVueI18n,
7374
I18nInjectionKey,
7475
I18nOptions,
7576
I18nAdditionalOptions,

packages/vue-i18n-core/test/i18n.test.ts

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ import {
2121
} from '@intlify/core-base'
2222
import { createEmitter } from '@intlify/shared'
2323
import { mount, pluralRules as _pluralRules } from './helper'
24-
import { createI18n, useI18n } from '../src/index'
24+
import { createI18n, useI18n, castToVueI18n } from '../src/i18n'
2525
import { errorMessages, I18nErrorCodes } from '../src/errors'
2626
import { Composer } from '../src/composer'
2727

@@ -30,6 +30,8 @@ import {
3030
IntlifyDevToolsHooks
3131
} from '@intlify/devtools-if'
3232

33+
import type { I18n } from '../src/i18n'
34+
3335
const container = document.createElement('div')
3436
document.body.appendChild(container)
3537

@@ -936,3 +938,25 @@ test('Intlify devtools hooking', () => {
936938
expect(fnI18nInit).toHaveBeenCalled()
937939
expect(fnTranslate).toHaveBeenCalled()
938940
})
941+
942+
describe('castToVueI18n', () => {
943+
test('succeeded', () => {
944+
const mockVueI18n = {
945+
version: '8.2.0'
946+
} as unknown as I18n
947+
expect(castToVueI18n(mockVueI18n)).toBe(mockVueI18n)
948+
})
949+
950+
test('failed', () => {
951+
const mockVueI18n = {} as unknown as I18n
952+
let error
953+
try {
954+
castToVueI18n(mockVueI18n)
955+
} catch (e) {
956+
error = e.message
957+
}
958+
expect(error).toEqual(
959+
errorMessages[I18nErrorCodes.NOT_COMPATIBLE_LEGACY_VUE_I18N]
960+
)
961+
})
962+
})

packages/vue-i18n/test/.gitkeep

Whitespace-only changes.

0 commit comments

Comments
 (0)