Skip to content

Commit

Permalink
feat: resolve locale message translation new API rt (#411)
Browse files Browse the repository at this point in the history
* feat: resolve locale message translation (rt)

closes #409

* update docs

* fix typo
  • Loading branch information
kazupon committed Mar 28, 2021
1 parent 565e1a0 commit 93fcfd6
Show file tree
Hide file tree
Showing 13 changed files with 785 additions and 45 deletions.
102 changes: 102 additions & 0 deletions docs/api/injection.md
Original file line number Diff line number Diff line change
Expand Up @@ -511,6 +511,108 @@ Overloaded `$t`. About details, see the [$t](injection#t-key) remarks.

Translation message

### $rt(message)

Resolve locale message translation

**Signature:**
```typescript
$rt(message: MessageFunction<VueMessageType> | VueMessageType): string;
```

**Details**

If this is used in a reactive context, it will re-evaluate once the locale changes.

In [Composition API mode](general#mode), the `$rt` is injected by `app.config.globalProperties`. The input / output is the same as for Composer, and it works on **global scope**. About that details, see [Composer#rt](composition#rt-message).

In [Legacy API mode](general#mode), the input / output is the same as for VueI18n instance. About details, see [VueI18n#rt](legacy#rt-message).

**See Also**
- [Scope and Locale Changing](../../guide/essentials/scope)
- [Composition API](../../guide/advanced/composition)

#### Parameters
| Parameter | Type | Description |
| --- | --- | --- |
| message | MessageFunction&lt;VueMessageType&gt; \| VueMessageType | A target locale message to be resolved. You will need to specify the locale message returned by `$tm`. |

#### Returns

Translation message

### $rt(message, plural, options)

Resolve locale message translation for plurals

**Signature:**
```typescript
$rt(message: MessageFunction<VueMessageType> | VueMessageType, plural: number, options?: TranslationOptions): string;
```

**Details**

Overloaded `$rt`. About details, see the [$rt](injection#rt-message) remarks.

#### Parameters
| Parameter | Type | Description |
| --- | --- | --- |
| message | MessageFunction&lt;VueMessageType&gt; \| VueMessageType | A target locale message to be resolved. You will need to specify the locale message returned by `$tm`. |
| plural | number | Which plural string to get. `1` returns the first one. |
| options | TranslateOptions | Additional [TranslateOptions](general#translateoptions) |

#### Returns

Translation message

### $rt(message, list, options)

Resolve locale message translation for list interpolations

**Signature:**
```typescript
$rt(message: MessageFunction<VueMessageType> | VueMessageType, list: unknown[], options?: TranslationOptions): string;
```

**Details**

Overloaded `$rt`. About details, see the [$rt](injection#rt-message) remarks.

#### Parameters
| Parameter | Type | Description |
| --- | --- | --- |
| message | MessageFunction&lt;VueMessageType&gt; \| VueMessageType | A target locale message to be resolved. You will need to specify the locale message returned by `$tm`. |
| list | unknown[] | A values of list interpolation. |
| options | TranslateOptions | Additional [TranslateOptions](general#translateoptions) |

#### Returns

Translation message

### $rt(message, named, options)

Resolve locale message translation for named interpolations

**Signature:**
```typescript
$rt(message: MessageFunction<VueMessageType> | VueMessageType, named: NamedValue, options?: TranslationOptions): string;
```

**Details**

Overloaded `$rt`. About details, see the [$rt](injection#rt-message) remarks.

#### Parameters
| Parameter | Type | Description |
| --- | --- | --- |
| message | MessageFunction&lt;VueMessageType&gt; \| VueMessageType | A target locale message to be resolved. You will need to specify the locale message returned by `$tm`. |
| named | NamedValue | A values of named interpolation. |
| options | TranslateOptions | Additional [TranslateOptions](general#translateoptions) |

#### Returns

Translation message

### $tc(key)

Locale message pluralization
Expand Down
1 change: 1 addition & 0 deletions docs/guide/advanced/composition.md
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,7 @@ This allows Vue I18n to inject the following properties and functions into the c
- `fallbackLocale`
- `availableLocales`
- `$t`: `t` function of Composer that is global scope
- `$rt`: `rt` function of Composer that is global scope
- `$d`: `d` function of Composer that is global scope
- `$n`: `n` function of Composer that is global scope
- `$tm`: `tm` function of Composer that is global scope
Expand Down
104 changes: 76 additions & 28 deletions packages/core-base/src/translate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,11 @@ export interface TranslateOptions {
* Whether do escape parameter for list or named interpolation values
*/
escapeParameter?: boolean
/**
* @remarks
* Whether the message has been resolved
*/
resolvedMessage?: boolean
}

// `translate` function overloads
Expand All @@ -161,6 +166,12 @@ export function translate<Messages, Message = string>(
plural: number,
options: TranslateOptions
): MessageType<Message> | number
export function translate<Messages, Message = string>(
context: CoreTranslationContext<Messages, Message>,
message: MessageFunction<Message> | string,
plural: number,
options: TranslateOptions
): MessageType<Message> | number
export function translate<Messages, Message = string>(
context: CoreTranslationContext<Messages, Message>,
key: Path | number,
Expand Down Expand Up @@ -195,6 +206,12 @@ export function translate<Messages, Message = string>(
list: unknown[],
options: TranslateOptions
): MessageType<Message> | number
export function translate<Messages, Message = string>(
context: CoreTranslationContext<Messages, Message>,
message: MessageFunction<Message> | string,
list: unknown[],
options: TranslateOptions
): MessageType<Message> | number
export function translate<Messages, Message = string>(
context: CoreTranslationContext<Messages, Message>,
key: Path | number,
Expand All @@ -218,6 +235,12 @@ export function translate<Messages, Message = string>(
named: NamedValue,
options: TranslateOptions
): MessageType<Message> | number
export function translate<Messages, Message = string>(
context: CoreTranslationContext<Messages, Message>,
message: MessageFunction<Message> | string,
named: NamedValue,
options: TranslateOptions
): MessageType<Message> | number
export function translate<Messages, Message = string>(
context: CoreTranslationContext<Messages, Message>,
...args: unknown[]
Expand All @@ -232,9 +255,10 @@ export function translate<Messages, Message = string>(
fallbackFormat,
postTranslation,
unresolving,
fallbackLocale
fallbackLocale,
messages
} = context
const [key, options] = parseTranslateArgs(...args)
const [key, options] = parseTranslateArgs<Message>(...args)

const missingWarn = isBoolean(options.missingWarn)
? options.missingWarn
Expand All @@ -248,8 +272,10 @@ export function translate<Messages, Message = string>(
? options.escapeParameter
: context.escapeParameter

const resolvedMessage = !!options.resolvedMessage

// prettier-ignore
const defaultMsgOrKey: string =
const defaultMsgOrKey =
isString(options.default) || isBoolean(options.default) // default by function option
? !isBoolean(options.default)
? options.default
Expand All @@ -265,28 +291,42 @@ export function translate<Messages, Message = string>(

// resolve message format
// eslint-disable-next-line prefer-const
let [format, targetLocale, message] = resolveMessageFormat(
context,
key,
locale,
fallbackLocale,
fallbackWarn,
missingWarn
)
let [format, targetLocale, message]: [
PathValue | MessageFunction<Message>,
Locale | undefined,
LocaleMessageValue<Message>
] = !resolvedMessage
? resolveMessageFormat(
context,
key as string,
locale,
fallbackLocale,
fallbackWarn,
missingWarn
)
: [
key,
locale,
((messages as unknown) as LocaleMessages<Message>)[locale] || {}
]

// if you use default message, set it as message format!
let cacheBaseKey = key
if (!(isString(format) || isMessageFunction<Message>(format))) {
if (
!resolvedMessage &&
!(isString(format) || isMessageFunction<Message>(format))
) {
if (enableDefaultMsg) {
format = defaultMsgOrKey
cacheBaseKey = format
cacheBaseKey = format as Path | MessageFunction<Message>
}
}

// checking message format and target locale
if (
!(isString(format) || isMessageFunction<Message>(format)) ||
!isString(targetLocale)
!resolvedMessage &&
(!(isString(format) || isMessageFunction<Message>(format)) ||
!isString(targetLocale))
) {
return unresolving ? NOT_REOSLVED : (key as MessageType<Message>)
}
Expand All @@ -308,14 +348,16 @@ export function translate<Messages, Message = string>(
}

// compile message format
const msg = compileMessageFormat(
context,
key,
targetLocale,
format,
cacheBaseKey,
errorDetector
)
const msg = !isMessageFunction(format)
? compileMessageFormat(
context,
key as string,
targetLocale!,
format,
cacheBaseKey as string,
errorDetector
)
: format

// if occurred compile error, return the message format
if (occurred) {
Expand All @@ -325,7 +367,7 @@ export function translate<Messages, Message = string>(
// evaluate message with context
const ctxOptions = getMessageContextOptions<Messages, Message>(
context,
targetLocale,
targetLocale!,
message,
options
)
Expand Down Expand Up @@ -562,16 +604,22 @@ function evaluateMessage<Messages, Message>(
}

/** @internal */
export function parseTranslateArgs(
export function parseTranslateArgs<Message = string>(
...args: unknown[]
): [Path, TranslateOptions] {
): [Path | MessageFunction<Message>, TranslateOptions] {
const [arg1, arg2, arg3] = args
const options = {} as TranslateOptions

if (!isString(arg1) && !isNumber(arg1)) {
if (!isString(arg1) && !isNumber(arg1) && !isMessageFunction(arg1)) {
throw createCoreError(CoreErrorCodes.INVALID_ARGUMENT)
}
const key = isNumber(arg1) ? String(arg1) : arg1

// prettier-ignore
const key = isNumber(arg1)
? String(arg1)
: isMessageFunction(arg1)
? (arg1 as MessageFunction<Message>)
: arg1

if (isNumber(arg2)) {
options.plural = arg2
Expand Down
36 changes: 36 additions & 0 deletions packages/core-base/test/translate.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ import { CoreErrorCodes, errorMessages } from '../src/errors'
import { registerMessageCompiler } from '../src/context'
import { compileToFunction } from '../src/compile'

import type { MessageContext } from '@intlify/runtime'

beforeEach(() => {
registerMessageCompiler(compileToFunction)
})
Expand Down Expand Up @@ -665,6 +667,40 @@ describe('error', () => {
})
})

test('resolvedMessage', () => {
const ctx = context({
locale: 'en',
messages: {
en: {}
}
})
expect(translate(ctx, 'car', 1, { resolvedMessage: true })).toEqual('car')
expect(
translate(ctx, () => 'hello!', 1, {
resolvedMessage: true
})
).toEqual('hello!')
expect(translate(ctx, 'list {0}', [1], { resolvedMessage: true })).toEqual(
'list 1'
)
expect(
translate(ctx, (ctx: MessageContext) => `list ${ctx.list(0)}`, [1], {
resolvedMessage: true
})
).toEqual('list 1')
expect(
translate(ctx, 'named {name}', { name: 'dio' }, { resolvedMessage: true })
).toEqual('named dio')
expect(
translate(
ctx,
(ctx: MessageContext) => `named ${ctx.named('name')}`,
{ name: 'dio' },
{ resolvedMessage: true }
)
).toEqual('named dio')
})

const enum ErrorCodes {
CODE1 = 1
}
Expand Down

0 comments on commit 93fcfd6

Please sign in to comment.