Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: resolve locale message translation new API rt #411

Merged
merged 3 commits into from
Mar 28, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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