Skip to content

Commit d0388f2

Browse files
committed
Merge branch 'master' of github.com:intlify/vue-i18n-next
2 parents 93a5141 + 10d7fe8 commit d0388f2

File tree

6 files changed

+115
-13
lines changed

6 files changed

+115
-13
lines changed

src/components/Translation.ts

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,17 @@
1-
import { h, Fragment, defineComponent, SetupContext, VNodeChild } from 'vue'
1+
import {
2+
h,
3+
Component,
4+
ComponentOptions,
5+
Fragment,
6+
defineComponent,
7+
SetupContext,
8+
VNodeChild
9+
} from 'vue'
210
import { Composer, ComposerInternal } from '../composer'
311
import { useI18n } from '../i18n'
412
import { TranslateOptions } from '../core'
513
import { NamedValue } from '../message/runtime'
6-
import { isNumber, isString } from '../utils'
14+
import { isNumber, isString, isObject } from '../utils'
715
import { baseFormatProps, BaseFormatProps } from './base'
816

917
export interface TranslationProps extends BaseFormatProps {
@@ -43,9 +51,12 @@ export const Translation = defineComponent({
4351
}
4452
const arg = getInterpolateArg(context, keys)
4553
const children = i18n.__transrateVNode(props.keypath, arg, options)
46-
return props.tag
54+
// prettier-ignore
55+
return isString(props.tag)
4756
? h(props.tag, { ...attrs }, children)
48-
: h(Fragment, { ...attrs }, children)
57+
: isObject(props.tag)
58+
? h(props.tag as Component | ComponentOptions, { ...attrs }, children)
59+
: h(Fragment, { ...attrs }, children)
4960
}
5061
}
5162
})

src/components/base.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,14 @@ import { I18nScope } from '../i18n'
55
export type ComponetI18nScope = Exclude<I18nScope, 'local'>
66

77
export interface BaseFormatProps {
8-
tag?: string
8+
tag?: string | object
99
locale?: Locale
1010
scope?: ComponetI18nScope
1111
}
1212

1313
export const baseFormatProps = {
1414
tag: {
15-
type: String
15+
type: [String, Object]
1616
},
1717
locale: {
1818
type: String

src/components/formatRenderer.ts

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
import {
22
h,
3+
Component,
4+
ComponentOptions,
35
RenderFunction,
46
Fragment,
57
SetupContext,
68
VNodeChild,
79
VNodeArrayChildren
810
} from 'vue'
911
import { NumberOptions, DateTimeOptions } from '../core'
10-
import { isString, isPlainObject, isArray } from '../utils'
12+
import { isString, isObject, isArray } from '../utils'
1113
import { BaseFormatProps } from './base'
1214

1315
export interface FormattableProps<Value, Format> extends BaseFormatProps {
@@ -45,7 +47,7 @@ export function renderFormatter<
4547

4648
if (isString(props.format)) {
4749
options.key = props.format
48-
} else if (isPlainObject(props.format)) {
50+
} else if (isObject(props.format)) {
4951
// eslint-disable-next-line @typescript-eslint/no-explicit-any
5052
if (isString((props.format as any).key)) {
5153
// eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -72,8 +74,11 @@ export function renderFormatter<
7274
children = [parts]
7375
}
7476

75-
return props.tag
77+
// prettier-ignore
78+
return isString(props.tag)
7679
? h(props.tag, { ...attrs }, children)
77-
: h(Fragment, { ...attrs }, children)
80+
: isObject(props.tag)
81+
? h(props.tag as Component | ComponentOptions, { ...attrs }, children)
82+
: h(Fragment, { ...attrs }, children)
7883
}
7984
}

test/components/DatetimeFormat.test.ts

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
*/
44

55
import { mount } from '../helper'
6-
import { defineComponent } from 'vue'
6+
import { defineComponent, SetupContext, VNodeChild, h } from 'vue'
77
import { createI18n } from '../../src/i18n'
88

99
const datetimeFormats = {
@@ -100,3 +100,33 @@ test('slots', async () => {
100100
/([1-9]|1[0-2])([1-9]|1[0-2])([1-9]|[1-3][0-9])(||||||) (|)([0-9]|1[0-2]):([0-5][0-9]):([0-5][0-9]) (|)/
101101
)
102102
})
103+
104+
test('component', async () => {
105+
const i18n = createI18n({
106+
locale: 'en-US',
107+
datetimeFormats
108+
})
109+
110+
const MyComponent = defineComponent({
111+
setup(props, context: SetupContext) {
112+
return (): VNodeChild => h('span', context.slots.default())
113+
}
114+
})
115+
116+
const App = defineComponent({
117+
data: () => ({ MyComponent }),
118+
template: `
119+
<i18n-d :tag="MyComponent" :value="new Date()"></i18n-d>
120+
<i18n-d :tag="MyComponent" :value="new Date()" format="long"></i18n-d>
121+
<i18n-d
122+
:tag="MyComponent"
123+
:value="new Date()"
124+
format="long"
125+
locale="ja-JP-u-ca-japanese"
126+
></i18n-d>
127+
`
128+
})
129+
const wrapper = await mount(App, i18n)
130+
131+
expect(wrapper.html().includes('span')).toBeTruthy()
132+
})

test/components/NumberFormat.test.ts

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
*/
44

55
import { mount } from '../helper'
6-
import { defineComponent } from 'vue'
6+
import { defineComponent, SetupContext, VNodeChild, h } from 'vue'
77
import { createI18n } from '../../src/i18n'
88

99
const numberFormats = {
@@ -93,3 +93,30 @@ test('slots', async () => {
9393
`<span style=\"color: green;\">€</span><span style=\"font-weight: bold;\">1</span><span style=\"font-weight: bold;\">,</span><span style=\"font-weight: bold;\">234</span>.<span style=\"font-size: small;\">00</span>`
9494
)
9595
})
96+
97+
test('component', async () => {
98+
const i18n = createI18n({
99+
locale: 'en-US',
100+
numberFormats
101+
})
102+
103+
const MyComponent = defineComponent({
104+
setup(props, context: SetupContext) {
105+
return (): VNodeChild => h('span', context.slots.default())
106+
}
107+
})
108+
109+
const App = defineComponent({
110+
data: () => ({ MyComponent }),
111+
template: `
112+
<i18n-n :tag="MyComponent" :value="100"></i18n-n>
113+
<i18n-n :tag="MyComponent" :value="100" format="currency"></i18n-n>
114+
<i18n-n :tag="MyComponent" :value="100" format="currency" locale="ja-JP"></i18n-n>
115+
`
116+
})
117+
const wrapper = await mount(App, i18n)
118+
119+
expect(wrapper.html()).toEqual(
120+
`<span>100</span><span>$100.00</span><span>¥100</span>`
121+
)
122+
})

test/components/Translation.test.ts

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
*/
44

55
import { mount } from '../helper'
6-
import { defineComponent, ref } from 'vue'
6+
import { h, defineComponent, SetupContext, VNodeChild, ref } from 'vue'
77
import { createI18n, useI18n } from '../../src/i18n'
88

99
const messages = {
@@ -182,3 +182,32 @@ test('scope', async () => {
182182

183183
expect(wrapper.html()).toEqual(`this is rootthis is global`)
184184
})
185+
186+
test('component', async () => {
187+
const i18n = createI18n({
188+
locale: 'en',
189+
messages
190+
})
191+
192+
const MyComponent = defineComponent({
193+
setup(props, context: SetupContext) {
194+
return (): VNodeChild => h('p', context.slots.default())
195+
}
196+
})
197+
198+
const App = defineComponent({
199+
data: () => ({ MyComponent }),
200+
template: `
201+
<i18n-t :tag="MyComponent" class="name" keypath="message.named">
202+
<template #name>
203+
<span>kazupon</span>
204+
</template>
205+
</i18n-t>
206+
`
207+
})
208+
const wrapper = await mount(App, i18n)
209+
210+
expect(wrapper.html()).toEqual(
211+
`<p class="name">hello, <span>kazupon</span>!</p>`
212+
)
213+
})

0 commit comments

Comments
 (0)