Skip to content

Commit a5e0010

Browse files
fix: not throw warnings when using implicit fallback (#1798)
* feat: don't show warning for same language * test: don't show warning for same language * fix: case of simply missing key * fix: consider nested case * fix: nested message case * use context message resolver * fix: simplify * fix: array or object of fallback pattern * fix: change the way of isImplicitFallback * test: add Explicit fallback with decision maps test
1 parent 826fe87 commit a5e0010

File tree

3 files changed

+103
-9
lines changed

3 files changed

+103
-9
lines changed

packages/core-base/src/context.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -692,4 +692,32 @@ export function updateFallbackLocale<Message = string>(
692692
ctx.localeFallbacker<Message>(ctx, fallback, locale)
693693
}
694694

695+
/** @internal */
696+
export function isAlmostSameLocale(
697+
locale: Locale,
698+
compareLocale: Locale
699+
): boolean {
700+
if (locale === compareLocale) return false
701+
return locale.split('-')[0] === compareLocale.split('-')[0]
702+
}
703+
704+
/** @internal */
705+
export function isImplicitFallback(
706+
targetLocale: Locale,
707+
locales: Locale[]
708+
): boolean {
709+
const index = locales.indexOf(targetLocale)
710+
if (index === -1) {
711+
return false
712+
}
713+
714+
for (let i = index + 1; i < locales.length; i++) {
715+
if (isAlmostSameLocale(targetLocale, locales[i])) {
716+
return true
717+
}
718+
}
719+
720+
return false
721+
}
722+
695723
/* eslint-enable @typescript-eslint/no-explicit-any */

packages/core-base/src/translate.ts

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ import { isMessageAST } from './compilation'
2020
import { createMessageContext } from './runtime'
2121
import {
2222
isTranslateFallbackWarn,
23+
isAlmostSameLocale,
24+
isImplicitFallback,
2325
handleMissing,
2426
NOT_REOSLVED,
2527
getAdditionalMeta,
@@ -839,6 +841,7 @@ function resolveMessageFormat<Messages, Message>(
839841
if (
840842
__DEV__ &&
841843
locale !== targetLocale &&
844+
!isAlmostSameLocale(locale, targetLocale) &&
842845
isTranslateFallbackWarn(fallbackWarn, key)
843846
) {
844847
onWarn(
@@ -905,15 +908,17 @@ function resolveMessageFormat<Messages, Message>(
905908
break
906909
}
907910

908-
const missingRet = handleMissing(
909-
context as any, // eslint-disable-line @typescript-eslint/no-explicit-any
910-
key,
911-
targetLocale,
912-
missingWarn,
913-
type
914-
)
915-
if (missingRet !== key) {
916-
format = missingRet as PathValue
911+
if (!isImplicitFallback(targetLocale, locales)) {
912+
const missingRet = handleMissing(
913+
context as any, // eslint-disable-line @typescript-eslint/no-explicit-any
914+
key,
915+
targetLocale,
916+
missingWarn,
917+
type
918+
)
919+
if (missingRet !== key) {
920+
format = missingRet as PathValue
921+
}
917922
}
918923
from = to
919924
}

packages/vue-i18n-core/test/issues.test.ts

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1359,6 +1359,67 @@ test('issue #1738', async () => {
13591359
expect(wrapper.find('#te2')?.textContent).toEqual(`true - expected true`)
13601360
})
13611361

1362+
describe('issue #1768', () => {
1363+
test('Implicit fallback using locales', async () => {
1364+
const mockWarn = vi.spyOn(shared, 'warn')
1365+
// eslint-disable-next-line @typescript-eslint/no-empty-function
1366+
mockWarn.mockImplementation(() => {})
1367+
1368+
const i18n = createI18n({
1369+
locale: 'en-US',
1370+
fallbackLocale: 'en',
1371+
messages: {
1372+
en: {
1373+
hello: {
1374+
'vue-i18n': 'Hello, Vue I18n'
1375+
}
1376+
}
1377+
}
1378+
})
1379+
1380+
const App = defineComponent({
1381+
template: `<div>{{ $t('hello.vue-i18n') }}</div>`
1382+
})
1383+
const wrapper = await mount(App, i18n)
1384+
1385+
expect(wrapper.html()).toEqual('<div>Hello, Vue I18n</div>')
1386+
expect(mockWarn).toHaveBeenCalledTimes(0)
1387+
})
1388+
1389+
test('Explicit fallback with decision maps', async () => {
1390+
const mockWarn = vi.spyOn(shared, 'warn')
1391+
// eslint-disable-next-line @typescript-eslint/no-empty-function
1392+
mockWarn.mockImplementation(() => {})
1393+
1394+
const i18n = createI18n({
1395+
locale: 'zh-Hant',
1396+
fallbackLocale: {
1397+
'de-CH': ['fr', 'it'],
1398+
'zh-Hant': ['zh-Hans'],
1399+
'es-CL': ['es-AR'],
1400+
es: ['en-GB'],
1401+
pt: ['es-AR'],
1402+
default: ['en', 'da']
1403+
},
1404+
messages: {
1405+
zh: {
1406+
hello: {
1407+
'vue-i18n': '你好,Vue I18n'
1408+
}
1409+
}
1410+
}
1411+
})
1412+
1413+
const App = defineComponent({
1414+
template: `<div>{{ $t('hello.vue-i18n') }}</div>`
1415+
})
1416+
const wrapper = await mount(App, i18n)
1417+
1418+
expect(wrapper.html()).toEqual('<div>你好,Vue I18n</div>')
1419+
expect(mockWarn).toHaveBeenCalledTimes(0)
1420+
})
1421+
})
1422+
13621423
test('#1796', async () => {
13631424
const i18n = createI18n({
13641425
locale: 'en',

0 commit comments

Comments
 (0)