Skip to content

fix: Support for te behavior compatibility before v9.6 #1751

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

Merged
merged 2 commits into from
Feb 29, 2024
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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