Skip to content

Commit 1b88ce8

Browse files
authored
fix: vue-i18n components scope resolving in Legacy API mode (#715)
closes #708
1 parent fa51b00 commit 1b88ce8

File tree

9 files changed

+84
-8
lines changed

9 files changed

+84
-8
lines changed

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,8 @@ export const DatetimeFormat = /* #__PURE__*/ defineComponent({
9494
setup(props, context): RenderFunction {
9595
const i18n =
9696
props.i18n ||
97-
(useI18n({ useScope: 'parent' }) as Composer & ComposerInternal)
97+
(useI18n({ useScope: 'parent', __useComponent: true }) as Composer &
98+
ComposerInternal)
9899

99100
return renderFormatter<
100101
FormattableProps<number | Date, Intl.DateTimeFormatOptions>,

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,8 @@ export const NumberFormat = /* #__PURE__*/ defineComponent({
8989
setup(props, context): RenderFunction {
9090
const i18n =
9191
props.i18n ||
92-
(useI18n({ useScope: 'parent' }) as Composer & ComposerInternal)
92+
(useI18n({ useScope: 'parent', __useComponent: true }) as Composer &
93+
ComposerInternal)
9394

9495
return renderFormatter<
9596
FormattableProps<number, Intl.NumberFormatOptions>,

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

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -116,8 +116,10 @@ export const Translation = /* #__PURE__*/ defineComponent({
116116
// NOTE: avoid https://github.com/microsoft/rushstack/issues/1050
117117
const i18n =
118118
props.i18n ||
119-
(useI18n({ useScope: props.scope as 'global' | 'parent' }) as Composer &
120-
ComposerInternal)
119+
(useI18n({
120+
useScope: props.scope as 'global' | 'parent',
121+
__useComponent: true
122+
}) as Composer & ComposerInternal)
121123
const keys = Object.keys(slots).filter(key => key !== '_')
122124

123125
return (): VNodeChild => {

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ import {
4949
EnableEmitter,
5050
DisableEmitter,
5151
SetPluralRulesSymbol,
52+
InejctWithOption,
5253
LegacyInstanceSymbol,
5354
__VUE_I18N_BRIDGE__
5455
} from './symbols'
@@ -565,6 +566,7 @@ export interface ComposerInternalOptions<
565566
__i18n?: CustomBlocks<VueMessageType>
566567
__i18nGlobal?: CustomBlocks<VueMessageType>
567568
__root?: Composer<Messages, DateTimeFormats, NumberFormats>
569+
__injectWithOption?: boolean
568570
}
569571

570572
/**
@@ -2488,6 +2490,7 @@ export function createComposer(options: any = {}, VueI18nLegacy?: any): any {
24882490
;(composer as any).getNumberFormat = getNumberFormat
24892491
;(composer as any).setNumberFormat = setNumberFormat
24902492
;(composer as any).mergeNumberFormat = mergeNumberFormat
2493+
;(composer as any)[InejctWithOption] = options.__injectWithOption
24912494
if (!__BRIDGE__) {
24922495
;(composer as any)[TransrateVNodeSymbol] = transrateVNode
24932496
;(composer as any)[NumberPartsSymbol] = numberParts

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

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import { I18nErrorCodes, createI18nError } from './errors'
2323
import {
2424
EnableEmitter,
2525
DisableEmitter,
26+
InejctWithOption,
2627
LegacyInstanceSymbol,
2728
__VUE_I18N_BRIDGE__
2829
} from './symbols'
@@ -710,7 +711,8 @@ export function useI18n<
710711
}
711712

712713
if (scope === 'parent') {
713-
let composer = getComposer(i18n, instance)
714+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
715+
let composer = getComposer(i18n, instance, (options as any).__useComponent)
714716
if (composer == null) {
715717
if (__DEV__) {
716718
warn(getWarnMessage(I18nWarnCodes.NOT_FOUND_PARENT_SCOPE))
@@ -893,7 +895,8 @@ function adjustI18nResources(
893895

894896
function getComposer(
895897
i18n: I18n,
896-
target: ComponentInternalInstance
898+
target: ComponentInternalInstance,
899+
useComponent = false
897900
): Composer | null {
898901
let composer: Composer | null = null
899902
const root = target.root
@@ -908,6 +911,10 @@ function getComposer(
908911
if (vueI18n != null) {
909912
composer = (vueI18n as VueI18n & VueI18nInternal)
910913
.__composer as Composer
914+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
915+
if (useComponent && !(composer as any)[InejctWithOption]) {
916+
composer = null
917+
}
911918
}
912919
}
913920
}

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1387,7 +1387,7 @@ function convertComposerOptions<
13871387
return messages
13881388
}, (messages || {}) as LocaleMessages<LocaleMessage<VueMessageType>>)
13891389
}
1390-
const { __i18n, __root } = options
1390+
const { __i18n, __root, __injectWithOption } = options
13911391

13921392
const datetimeFormats = options.datetimeFormats
13931393
const numberFormats = options.numberFormats
@@ -1413,7 +1413,8 @@ function convertComposerOptions<
14131413
messageResolver: options.messageResolver,
14141414
inheritLocale,
14151415
__i18n,
1416-
__root
1416+
__root,
1417+
__injectWithOption
14171418
}
14181419
}
14191420

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ export function defineMixin(
5757
if (this === this.$root) {
5858
this.$i18n = mergeToRoot(vuei18n, optionsI18n)
5959
} else {
60+
optionsI18n.__injectWithOption = true
6061
this.$i18n = createVueI18n(optionsI18n)
6162
}
6263
} else if (options.__i18n) {
@@ -65,6 +66,7 @@ export function defineMixin(
6566
} else {
6667
this.$i18n = createVueI18n({
6768
__i18n: (options as ComposerInternalOptions).__i18n,
69+
__injectWithOption: true,
6870
__root: composer
6971
} as VueI18nOptions)
7072
}

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,6 @@ export const DisableEmitter = /* #__PURE__*/ makeSymbol('__disableEmitter')
99
export const SetPluralRulesSymbol = makeSymbol('__setPluralRules')
1010
export const DevToolsMetaSymbol = makeSymbol('__intlifyMeta')
1111
export const LegacyInstanceSymbol = /* #__PURE__*/ makeSymbol('__legacyVueI18n')
12+
export const InejctWithOption = /* #__PURE__*/ makeSymbol('__injectWithOption')
1213

1314
export const __VUE_I18N_BRIDGE__ = /* #__PURE__*/ '__VUE_I18N_BRIDGE__'

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

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,3 +276,61 @@ test('message resolver', async () => {
276276
expect(mockMessageResolver.mock.calls[0][0]).toEqual(en)
277277
expect(mockMessageResolver.mock.calls[0][1]).toEqual('message.named')
278278
})
279+
280+
test('issue #708', async () => {
281+
const i18n = createI18n({
282+
legacy: true,
283+
locale: 'en',
284+
messages
285+
})
286+
287+
const C2 = defineComponent({
288+
template: `<div>C2 slot: <slot></slot></div>`
289+
})
290+
291+
const C1 = defineComponent({
292+
components: {
293+
C2
294+
},
295+
template: `<div>
296+
C1:
297+
<div>{{ $t("hello", { world: $t("world") }) }}</div>
298+
<i18n-t keypath="hello" tag="div">
299+
<template #world>
300+
<strong>{{ $t("world") }}</strong>
301+
</template>
302+
</i18n-t>
303+
304+
<br />
305+
306+
<C2>
307+
<div>{{ $t("hello", { world: $t("world") }) }}</div>
308+
<i18n-t keypath="hello" tag="div">
309+
<template #world>
310+
<strong>{{ $t("world") }}</strong>
311+
</template>
312+
</i18n-t>
313+
</C2>
314+
</div>`,
315+
i18n: {
316+
messages: {
317+
en: {
318+
hello: 'Hello {world}',
319+
world: 'world!'
320+
}
321+
}
322+
}
323+
})
324+
325+
const App = defineComponent({
326+
components: {
327+
C1
328+
},
329+
template: `<C1 />`
330+
})
331+
const wrapper = await mount(App, i18n)
332+
333+
expect(wrapper.html()).toEqual(
334+
`<div> C1: <div>Hello world!</div><div>Hello <strong>world!</strong></div><br><div>C2 slot: <div>Hello world!</div><div>Hello <strong>world!</strong></div></div></div>`
335+
)
336+
})

0 commit comments

Comments
 (0)