Skip to content

Commit

Permalink
fix: Support for te behavior compatibility before v9.6 (#1751)
Browse files Browse the repository at this point in the history
* fix: Support for `te` behavior compatibility before v9.6

* fix: warning once
  • Loading branch information
kazupon committed Feb 29, 2024
1 parent 6a66289 commit 7d28dd2
Show file tree
Hide file tree
Showing 8 changed files with 130 additions and 26 deletions.
2 changes: 1 addition & 1 deletion packages/petite-vue-i18n/src/vue.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -864,7 +864,7 @@ declare module '@vue/runtime-core' {
* @param key - A target locale message key
* @param locale - A locale, optional, override locale that global scope or local scope
*
* @returns If found locale message, `true`, else `false`, Note that `false` is returned even if the value present in the Key is not translatable.
* @returns If found locale message, `true`, else `false`, Note that `false` is returned even if the value present in the key is not translatable, yet if `translateExistCompatible` is set to `true`, it will return `true` if the key is available, even if the value is translatable.
*/
$te<
Key extends string,
Expand Down
2 changes: 1 addition & 1 deletion packages/vue-i18n-bridge/src/vue.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -869,7 +869,7 @@ declare module '@vue/runtime-core' {
* @param key - A target locale message key
* @param locale - A locale, optional, override locale that global scope or local scope
*
* @returns If found locale message, `true`, else `false`, Note that `false` is returned even if the value present in the Key is not translatable.
* @returns If found locale message, `true`, else `false`, Note that `false` is returned even if the value present in the key is not translatable, yet if `translateExistCompatible` is set to `true`, it will return `true` if the key is available, even if the value is translatable.
*/
$te<
Key extends string,
Expand Down
44 changes: 37 additions & 7 deletions packages/vue-i18n-core/src/composer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ import {
assign,
inBrowser,
deepCopy,
hasOwn
hasOwn,
warnOnce
} from '@intlify/shared'
import {
isTranslateFallbackWarn,
Expand Down Expand Up @@ -614,6 +615,24 @@ export interface ComposerOptions<
* @defaultValue `undefined`
*/
messageCompiler?: MessageCompiler
/**
* @remarks
* An option to make `te` behavior specification before v9.6
*
* @VueI18nTip
* :new: v9.10+
*
* @VueI18nWarning
* This flag will be removed in v10.
*
* @VueI18nSee [GitHub Issue](https://github.com/intlify/vue-i18n-next/issues/1738)
*
* @VueI18nSee [`te`](composition#te-key-locale)
*
* @defaultValue `false`
*
*/
translateExistCompatible?: boolean
}

/**
Expand Down Expand Up @@ -1383,7 +1402,7 @@ export interface Composer<
* @param key - A target locale message key
* @param locale - A locale, it will be used over than global scope or local scope
*
* @returns If found locale message, `true`, else `false`, Note that `false` is returned even if the value present in the Key is not translatable.
* @returns If found locale message, `true`, else `false`, Note that `false` is returned even if the value present in the key is not translatable, yet if `translateExistCompatible` is set to `true`, it will return `true` if the key is available, even if the value is translatable.
*/
te<
Str extends string,
Expand Down Expand Up @@ -1860,6 +1879,17 @@ export function createComposer(options: any = {}, VueI18nLegacy?: any): any {
const flatJson = options.flatJson
const _ref = inBrowser ? ref : shallowRef

const translateExistCompatible = !!options.translateExistCompatible
if (__DEV__) {
if (translateExistCompatible && !__TEST__) {
warnOnce(
getWarnMessage(
I18nWarnCodes.NOTICE_DROP_TRANSLATE_EXIST_COMPATIBLE_FLAG
)
)
}
}

let _inheritLocale = isBoolean(options.inheritLocale)
? options.inheritLocale
: true
Expand Down Expand Up @@ -2357,11 +2387,11 @@ export function createComposer(options: any = {}, VueI18nLegacy?: any): any {
const targetLocale = isString(locale) ? locale : _locale.value
const message = getLocaleMessage(targetLocale)
const resolved = _context.messageResolver(message, key)
return (
isMessageAST(resolved) ||
isMessageFunction(resolved) ||
isString(resolved)
)
return !translateExistCompatible
? isMessageAST(resolved) ||
isMessageFunction(resolved) ||
isString(resolved)
: resolved != null
},
() => [key],
'translate exists',
Expand Down
24 changes: 12 additions & 12 deletions packages/vue-i18n-core/src/i18n.ts
Original file line number Diff line number Diff line change
Expand Up @@ -234,10 +234,10 @@ export interface I18n<
* An instance of this property is **global scope***.
*/
readonly global: Legacy extends true
? VueI18n<Messages, DateTimeFormats, NumberFormats, OptionLocale>
: Legacy extends false
? Composer<Messages, DateTimeFormats, NumberFormats, OptionLocale>
: unknown
? VueI18n<Messages, DateTimeFormats, NumberFormats, OptionLocale>
: Legacy extends false
? Composer<Messages, DateTimeFormats, NumberFormats, OptionLocale>
: unknown
/**
* The property whether or not the Composition API is available
*
Expand Down Expand Up @@ -529,17 +529,17 @@ export function createI18n(options: any = {}, VueI18nLegacy?: any): any {
// prettier-ignore
const __legacyMode = __LITE__
? false
: __FEATURE_LEGACY_API__ && isBoolean(options.legacy)
: __FEATURE_LEGACY_API__ && isBoolean(options.legacy)
? options.legacy
: __FEATURE_LEGACY_API__
// prettier-ignore
const __globalInjection = isBoolean(options.globalInjection)
? options.globalInjection
: true
? options.globalInjection
: true
// prettier-ignore
const __allowComposition = __LITE__
? true
: __FEATURE_LEGACY_API__ && __legacyMode
: __FEATURE_LEGACY_API__ && __legacyMode
? !!options.allowComposition
: true
const __instances = new Map<ComponentInternalInstance, VueI18n | Composer>()
Expand Down Expand Up @@ -1228,10 +1228,10 @@ function useI18nForLegacy(
const _locale = ref<Locale>(
// prettier-ignore
!isLocalScope || _inheritLocale
? root.locale.value
: isString(options.locale)
? options.locale
: DEFAULT_LOCALE
? root.locale.value
: isString(options.locale)
? options.locale
: DEFAULT_LOCALE
)

const _fallbackLocale = ref<FallbackLocale>(
Expand Down
3 changes: 3 additions & 0 deletions packages/vue-i18n-core/src/legacy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1376,6 +1376,8 @@ function convertComposerOptions<
const datetimeFormats = options.datetimeFormats
const numberFormats = options.numberFormats
const flatJson = options.flatJson
const translateExistCompatible = (options as unknown as ComposerOptions)
.translateExistCompatible

return {
locale,
Expand All @@ -1396,6 +1398,7 @@ function convertComposerOptions<
escapeParameter,
messageResolver: options.messageResolver,
inheritLocale,
translateExistCompatible,
__i18n,
__root,
__injectWithOption
Expand Down
6 changes: 4 additions & 2 deletions packages/vue-i18n-core/src/warnings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ export const I18nWarnCodes = {
COMPONENT_NAME_LEGACY_COMPATIBLE: inc(), // 14
NOT_FOUND_PARENT_SCOPE: inc(), // 15
IGNORE_OBJ_FLATTEN: inc(), // 16
NOTICE_DROP_ALLOW_COMPOSITION: inc() // 17
NOTICE_DROP_ALLOW_COMPOSITION: inc(), // 17
NOTICE_DROP_TRANSLATE_EXIST_COMPATIBLE_FLAG: inc() // 18
} as const

type I18nWarnCodes = (typeof I18nWarnCodes)[keyof typeof I18nWarnCodes]
Expand All @@ -27,7 +28,8 @@ export const warnMessages: { [code: number]: string } = {
[I18nWarnCodes.COMPONENT_NAME_LEGACY_COMPATIBLE]: `Component name legacy compatible: '{name}' -> 'i18n'`,
[I18nWarnCodes.NOT_FOUND_PARENT_SCOPE]: `Not found parent scope. use the global scope.`,
[I18nWarnCodes.IGNORE_OBJ_FLATTEN]: `Ignore object flatten: '{key}' key has an string value`,
[I18nWarnCodes.NOTICE_DROP_ALLOW_COMPOSITION]: `'allowComposition' option will be dropped in the next major version. For more information, please see 👉 https://tinyurl.com/2p97mcze`
[I18nWarnCodes.NOTICE_DROP_ALLOW_COMPOSITION]: `'allowComposition' option will be dropped in the next major version. For more information, please see 👉 https://tinyurl.com/2p97mcze`,
[I18nWarnCodes.NOTICE_DROP_TRANSLATE_EXIST_COMPATIBLE_FLAG]: `'translateExistCompatible' option will be dropped in the next major version.`
}

export function getWarnMessage(
Expand Down
73 changes: 71 additions & 2 deletions packages/vue-i18n-core/test/issues.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ import {
withDirectives,
resolveDirective,
nextTick,
getCurrentInstance
getCurrentInstance,
onMounted
} from 'vue'
import {
setDevToolsHook,
Expand Down Expand Up @@ -1229,7 +1230,6 @@ test('issue #1610', async () => {
})

test('issue #1615', async () => {
console.log('----')
const en = {
hello: (() => {
const fn = ctx => {
Expand Down Expand Up @@ -1289,3 +1289,72 @@ test('issue #1717', async () => {
'a.b.c': 'Hello, Vue I18n' // should not be transformed to nested object like in issue
})
})

test('issue #1738', async () => {
const resources = {
en: {
messages: {
common: {
actions: {
cancel: 'Cancel'
}
}
}
},
nl: {
messages: {
common: {
actions: {
cancel: 'Cancel'
}
}
}
}
}

function loadTranslations(): Promise<typeof resources> {
return new Promise(resolve => resolve(resources))
}

function delay(ms: number) {
return new Promise(resolve => setTimeout(resolve, ms))
}

const i18n = createI18n({
locale: 'nl',
legacy: false,
translateExistCompatible: true,
fallbackLocale: 'en',
missingWarn: false,
silentFallbackWarn: true
})

const App = defineComponent({
setup() {
const { mergeLocaleMessage, te } = useI18n()
onMounted(() => {
setTimeout(async () => {
const data = await loadTranslations()

for (const key in data) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const { messages } = (data as any)[key]
mergeLocaleMessage(key, messages)
}
}, 100)
})
return { te }
},
template: `<div>
<p id="te1">{{ te('common') }} - expected true</p>
<p id="te2">{{ te('common.actions') }} - expected true</p>
</div>`
})

const wrapper = await mount(App, i18n)

await delay(110)

expect(wrapper.find('#te1')?.textContent).toEqual(`true - expected true`)
expect(wrapper.find('#te2')?.textContent).toEqual(`true - expected true`)
})
2 changes: 1 addition & 1 deletion packages/vue-i18n/src/vue.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -869,7 +869,7 @@ declare module '@vue/runtime-core' {
* @param key - A target locale message key
* @param locale - A locale, optional, override locale that global scope or local scope
*
* @returns If found locale message, `true`, else `false`, Note that `false` is returned even if the value present in the Key is not translatable.
* @returns If found locale message, `true`, else `false`, Note that `false` is returned even if the value present in the key is not translatable, yet if `translateExistCompatible` is set to `true`, it will return `true` if the key is available, even if the value is translatable.
*/
$te<
Key extends string,
Expand Down

0 comments on commit 7d28dd2

Please sign in to comment.