Skip to content

Commit 7d703eb

Browse files
authored
feat: how to get locale messages from a given key (#87)
* feat: the way to get locale messages from the specified key * update docs
1 parent 2dd1d15 commit 7d703eb

File tree

6 files changed

+125
-6
lines changed

6 files changed

+125
-6
lines changed

README.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,6 @@ See the below examples:
6060
- [Example with using Composable API](https://github.com/intlify/vue-i18n-next/blob/master/examples/composable/components/datetime-format.html)
6161
- [Example with using Legacy API](https://github.com/intlify/vue-i18n-next/blob/master/examples/legacy/components/datetime-format.html)
6262

63-
6463
## :lollipop: Examples
6564

6665
See the [`examples`](https://github.com/intlify/vue-i18n-next/tree/master/examples) directory.
@@ -79,7 +78,9 @@ The examples are offered that use the following two API styles:
7978

8079
#### APIs
8180
- The return value of `$t` and `t` methods is **string** only. object and array values ​​are no longer returned.
81+
- As an alternative way, you can use `$tm` / `tm`
8282
- The return value of `$tc` and `tc` methods is **string** only. object and array values ​​are no longer returned.
83+
- As an alternative way, you can use `$tm` / `tm`
8384
- `VueI18n` class cannot used with `new`. It can only be used via the `$i18n` property of Vue instance.
8485
- In vue-i18n-next, by replacing `new VueI18n` with `createI18n`, you can use existing `VueI18n` options as they are.
8586
- See the `examples/legacy` directory.
@@ -191,6 +192,7 @@ yarn add vue-i18n@next
191192
- [x] setPostTranslationHandler
192193
- [x] getMissingHandler
193194
- [x] setMissingHandler
195+
- [x] tm
194196
- Legacy API: compatible supporting
195197
- VueI18n
196198
- [x] locale
@@ -225,13 +227,15 @@ yarn add vue-i18n@next
225227
- [x] setNumberFormat
226228
- [x] mergeNumberFormat
227229
- [x] getChoiceIndex
230+
- [x] tm
228231
- Inejctted in Vue Prototype API
229232
- [x] $i18n
230233
- [x] $t
231234
- [x] $tc
232235
- [x] $te
233236
- [x] $d
234237
- [x] $n
238+
- [x] $tm
235239
- Component options
236240
- [x] messages
237241
- [x] pluralRule

src/composer.ts

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import {
1717
VNodeArrayChildren
1818
} from 'vue'
1919
import { WritableComputedRef, ComputedRef } from '@vue/reactivity'
20-
import { Path, parse as parsePath } from './path'
20+
import { Path, parse as parsePath, resolveValue } from './path'
2121
import {
2222
DateTimeFormats as DateTimeFormatsType,
2323
NumberFormats as NumberFormatsType,
@@ -34,6 +34,7 @@ import {
3434
} from './message/runtime'
3535
import {
3636
Locale,
37+
LocaleMessageValue,
3738
LocaleMessages,
3839
createRuntimeContext,
3940
RuntimeContext,
@@ -195,6 +196,7 @@ export interface Composer<
195196
n(value: number, key: string, locale: Locale): string
196197
n(value: number, options: NumberOptions): string
197198
n(...args: unknown[]): string // for internal
199+
tm(key: Path): LocaleMessageValue<Message> | {}
198200
getLocaleMessage(locale: Locale): LocaleMessageDictionary<Message>
199201
setLocaleMessage(
200202
locale: Locale,
@@ -696,6 +698,18 @@ export function createComposer<
696698
)
697699
}
698700

701+
// tm
702+
function tm(key: Path): LocaleMessageValue<Message> | {} {
703+
const messages = _messages.value[_locale.value] || {}
704+
const target = resolveValue(messages, key)
705+
// prettier-ignore
706+
return target != null
707+
? target as LocaleMessageValue<Message>
708+
: __root
709+
? __root.tm(key) as LocaleMessageValue<Message> || {}
710+
: {}
711+
}
712+
699713
// getLocaleMessage
700714
function getLocaleMessage(locale: Locale): LocaleMessageDictionary<Message> {
701715
return (_messages.value[locale] || {}) as LocaleMessageDictionary<Message>
@@ -869,6 +883,7 @@ export function createComposer<
869883
t,
870884
d,
871885
n,
886+
tm,
872887
getLocaleMessage,
873888
setLocaleMessage,
874889
mergeLocaleMessage,

src/legacy.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ import {
1616
LocaleMessages,
1717
LocaleMessageDictionary,
1818
PostTranslationHandler,
19-
FallbackLocale
19+
FallbackLocale,
20+
LocaleMessageValue
2021
} from './core/context'
2122
import { TranslateOptions } from './core/translate'
2223
import {
@@ -139,6 +140,7 @@ export interface VueI18n<
139140
tc(key: Path, choice: number, named: Record<string, unknown>): TranslateResult
140141
tc(...args: unknown[]): TranslateResult // for $tc
141142
te(key: Path, locale?: Locale): boolean
143+
tm(key: Path): LocaleMessageValue<VueMessageType> | {}
142144
getLocaleMessage(locale: Locale): LocaleMessageDictionary<VueMessageType>
143145
setLocaleMessage(
144146
locale: Locale,
@@ -510,6 +512,11 @@ export function createVueI18n<
510512
return resolveValue(message, key) !== null
511513
},
512514

515+
// tm
516+
tm(key: Path): LocaleMessageValue<VueMessageType> | {} {
517+
return composer.tm(key)
518+
},
519+
513520
// getLocaleMessage
514521
getLocaleMessage(locale: Locale): LocaleMessageDictionary<VueMessageType> {
515522
return composer.getLocaleMessage(locale)

src/mixin.ts

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
11
import { ComponentOptions, getCurrentInstance } from 'vue'
22
import { Path } from './path'
3-
import { Locale } from './core/context'
4-
import { Composer, ComposerInternalOptions, CustomBlocks } from './composer'
3+
import { Locale, LocaleMessageValue } from './core/context'
4+
import {
5+
Composer,
6+
ComposerInternalOptions,
7+
CustomBlocks,
8+
VueMessageType
9+
} from './composer'
510
import {
611
VueI18n,
712
VueI18nInternal,
@@ -134,6 +139,20 @@ declare module '@vue/runtime-core' {
134139
* This property is supported for legacy API only
135140
*/
136141
$n?: (...args: unknown[]) => NumberFormatResult
142+
/**
143+
* translation messages method
144+
*
145+
* @param key - required, target keypath
146+
* @returns locale messages
147+
*
148+
* @remarks
149+
* Get the locale message of `key`.
150+
* Get in preferentially component locale messages than global locale messages.
151+
* If the target locale messages is not found locally, get it from the global, otherwise returns an empty object.
152+
*
153+
* This property is supported for legacy API only
154+
*/
155+
$tm?: (key: Path) => LocaleMessageValue<VueMessageType> | {}
137156
}
138157
}
139158

@@ -206,6 +225,8 @@ export function defineMixin<Messages, DateTimeFormats, NumberFormats>(
206225
this.$i18n.d(...args)
207226
this.$n = (...args: unknown[]): NumberFormatResult =>
208227
this.$i18n.n(...args)
228+
this.$tm = (key: Path): LocaleMessageValue<VueMessageType> | {} =>
229+
this.$i18n.tm(key)
209230
},
210231

211232
mounted(): void {
@@ -226,6 +247,7 @@ export function defineMixin<Messages, DateTimeFormats, NumberFormats>(
226247
delete this.$te
227248
delete this.$d
228249
delete this.$n
250+
delete this.$tm
229251

230252
i18n.__deleteInstance(instance)
231253
delete this.$i18n

test/composer.test.ts

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import {
1616
VueMessageType
1717
} from '../src/composer'
1818
import { generateFormatCacheKey } from '../src/utils'
19-
import { watch, nextTick, Text, createVNode } from 'vue'
19+
import { watch, watchEffect, nextTick, Text, createVNode } from 'vue'
2020

2121
describe('locale', () => {
2222
test('default value', () => {
@@ -670,6 +670,41 @@ describe('n', () => {
670670
})
671671
})
672672

673+
test('tm', async () => {
674+
const composer = createComposer({
675+
locale: 'ja',
676+
messages: {
677+
en: {},
678+
ja: {
679+
foo: {
680+
bar: {
681+
buz: 'hello'
682+
},
683+
codes: {
684+
errors: ['error1', 'error2']
685+
}
686+
}
687+
}
688+
}
689+
})
690+
691+
let messages1 = composer.tm('foo.bar')
692+
let messages2 = composer.tm('foo.codes')
693+
expect(messages1).toEqual({ buz: 'hello' })
694+
expect(messages2).toEqual({ errors: ['error1', 'error2'] })
695+
696+
watchEffect(() => {
697+
messages1 = composer.tm('foo.bar')
698+
messages2 = composer.tm('foo.codes')
699+
})
700+
701+
composer.locale.value = 'en'
702+
await nextTick()
703+
704+
expect(messages1).toEqual({})
705+
expect(messages2).toEqual({})
706+
})
707+
673708
describe('getLocaleMessage / setLocaleMessage / mergeLocaleMessage', () => {
674709
test('basic', () => {
675710
const {

test/legacy.test.ts

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import { warn } from '../src/utils'
1010
import { createVueI18n } from '../src/legacy'
1111
import { errorMessages, I18nErrorCodes } from '../src/errors'
1212
import { getWarnMessage, I18nWarnCodes } from '../src/warnings'
13+
import { watchEffect, nextTick } from 'vue'
1314

1415
test('locale', () => {
1516
const i18n = createVueI18n()
@@ -234,6 +235,41 @@ test('te', () => {
234235
expect(i18n.te('message.hallo', 'ja')).toEqual(false)
235236
})
236237

238+
test('tm', async () => {
239+
const i18n = createVueI18n({
240+
locale: 'ja',
241+
messages: {
242+
en: {},
243+
ja: {
244+
foo: {
245+
bar: {
246+
buz: 'hello'
247+
},
248+
codes: {
249+
errors: ['error1', 'error2']
250+
}
251+
}
252+
}
253+
}
254+
})
255+
256+
let messages1 = i18n.tm('foo.bar')
257+
let messages2 = i18n.tm('foo.codes')
258+
expect(messages1).toEqual({ buz: 'hello' })
259+
expect(messages2).toEqual({ errors: ['error1', 'error2'] })
260+
261+
watchEffect(() => {
262+
messages1 = i18n.tm('foo.bar')
263+
messages2 = i18n.tm('foo.codes')
264+
})
265+
266+
i18n.locale = 'en'
267+
await nextTick()
268+
269+
expect(messages1).toEqual({})
270+
expect(messages2).toEqual({})
271+
})
272+
237273
test('getLocaleMessage / setLocaleMessage / mergeLocaleMessage', () => {
238274
const i18n = createVueI18n({
239275
messages: {

0 commit comments

Comments
 (0)