Skip to content

Commit

Permalink
fix: Resolve the message in components which was rendered with slots,…
Browse files Browse the repository at this point in the history
… for about `<i18n-t>`, `<i18n-n>` and `<i18n-d>` (#1416)

* fix: Resolve the message in the render component in which the slot was rendered, for `<i18n-t>`, `<i18n-n>` and `<i18n-d>`

* fix: for bridge
  • Loading branch information
kazupon committed Jun 1, 2023
1 parent 59e5452 commit ea7f768
Show file tree
Hide file tree
Showing 3 changed files with 181 additions and 4 deletions.
22 changes: 21 additions & 1 deletion packages/vue-i18n-core/src/i18n.ts
Expand Up @@ -1021,7 +1021,10 @@ function getComposer(
): Composer | null {
let composer: Composer | null = null
const root = target.root
let current: ComponentInternalInstance | null = target.parent
let current: ComponentInternalInstance | null = getParentComponentInstance(
target,
useComponent
)
while (current != null) {
const i18nInternal = i18n as unknown as I18nInternal
if (i18n.mode === 'composition') {
Expand Down Expand Up @@ -1053,6 +1056,23 @@ function getComposer(
return composer
}

function getParentComponentInstance(
target: ComponentInternalInstance | null,
useComponent = false
) {
if (target == null) {
return null
}
if (!__BRIDGE__) {
// if `useComponent: true` will be specified, we get lexical scope owner instance for use-case slots
return !useComponent
? target.parent
: (target.vnode as any).ctx || target.parent // eslint-disable-line @typescript-eslint/no-explicit-any
} else {
return target.parent
}
}

function setupLifeCycle(
i18n: I18nInternal,
target: ComponentInternalInstance,
Expand Down
4 changes: 2 additions & 2 deletions packages/vue-i18n-core/test/components/Translation.test.ts
Expand Up @@ -189,7 +189,7 @@ test('scope', async () => {
`
})

const Root = defineComponent({
const App = defineComponent({
components: {
Container
},
Expand All @@ -208,7 +208,7 @@ test('scope', async () => {
template: `<Container>`
})

const wrapper = await mount(Root, i18n)
const wrapper = await mount(App, i18n)

expect(wrapper.html()).toEqual(`this is rootthis is global`)
})
Expand Down
159 changes: 158 additions & 1 deletion packages/vue-i18n-core/test/issues.test.ts
Expand Up @@ -18,7 +18,8 @@ import {
h,
withDirectives,
resolveDirective,
nextTick
nextTick,
getCurrentInstance
} from 'vue'
import {
setDevToolsHook,
Expand All @@ -32,6 +33,8 @@ import {
import { createI18n, useI18n } from '../src/i18n'
import { mount } from './helper'

import type { ComponentOptions } from 'vue'

const container = document.createElement('div')
document.body.appendChild(container)

Expand Down Expand Up @@ -292,6 +295,92 @@ describe('issue #722', () => {
})
})

test('issue #729', async () => {
const i18n = createI18n({
legacy: true,
locale: 'en',
messages
})

const C3 = defineComponent({
template: `<div>C3 slot: <slot></slot></div>`,
i18n: {
messages: {
en: {
hello: 'Hello {world} - C3',
world: 'world! - C3'
}
}
}
})

const C2 = defineComponent({
template: `<div>C2 slot: <slot></slot></div>`,
i18n: {
messages: {
en: {
goodbuy: 'Goodbuy!'
}
}
}
})

const C1 = defineComponent({
components: {
C2,
C3
},
template: `<div>
C1:
<div>{{ $t("hello", { world: $t("world") }) }}</div>
<i18n-t keypath="hello" tag="div">
<template #world>
<strong>{{ $t("world") }}</strong>
</template>
</i18n-t>
<br />
<C2>
<div>{{ $t("hello", { world: $t("world") }) }}</div>
<i18n-t keypath="hello" tag="div">
<template #world>
<strong>{{ $t("world") }}</strong>
</template>
</i18n-t>
</C2>
<C3>
<div>{{ $t("hello", { world: $t("world") }) }}</div>
<i18n-t keypath="hello" tag="div">
<template #world>
<strong>{{ $t("world") }}</strong>
</template>
</i18n-t>
</C3>
</div>`,
i18n: {
messages: {
en: {
hello: 'Hello {world}',
world: 'world!'
}
}
}
})

const App = defineComponent({
components: {
C1
},
template: `<C1 />`
})
const wrapper = await mount(App, i18n)

expect(wrapper.html()).toEqual(
`<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>C3 slot: <div>Hello world!</div><div>Hello <strong>world!</strong></div></div></div>`
)
})

test('issue #819: v-for', async () => {
const i18n = createI18n({
legacy: false,
Expand Down Expand Up @@ -722,3 +811,71 @@ test('issue #1123', async () => {
`hello, <span>Hello</span>! Do you like <a><strong>Vue </strong> I18n </a>?`
)
})

test('issue #1392', async () => {
const i18n = createI18n({
legacy: false,
locale: 'en',
messages: {
en: { hello: 'world' }
}
})

const Test = defineComponent({
setup() {
const instance = getCurrentInstance()
if (instance == null) {
throw new Error()
}
// emulate i18n custom block
const options = instance.type as ComponentOptions
options.__i18n = [
{
locale: 'en',
resource: {
any: 'thing'
}
}
]
const { t } = useI18n()
return { t }
},
template: `<slot />`
})

const App = defineComponent({
components: {
Test
},
setup() {
const instance = getCurrentInstance()
if (instance == null) {
throw new Error()
}
// emulate i18n custom block
const options = instance.type as ComponentOptions
options.__i18n = [
{
locale: 'en',
resource: {
doesNotWork: 'works'
}
}
]
const { t } = useI18n()

return { t }
},
template: `<div>
<Test>
component: <i18n-t keypath="doesNotWork" />
<br />
t: {{ t('doesNotWork') }}
</Test>
</div>`
})

const wrapper = await mount(App, i18n)

expect(wrapper.html()).toEqual(`<div> component: works<br> t: works</div>`)
})

0 comments on commit ea7f768

Please sign in to comment.