Skip to content

Commit

Permalink
feat: add a new option fallbackRootWithEmptyString (#1441)
Browse files Browse the repository at this point in the history
* feat: add new option fallbackRootWithEmptyString

* feat: add fallbackRootWithEmptyString in index.d.ts and api.md
  • Loading branch information
PeterAlfredLee authored Jan 21, 2022
1 parent bd551c0 commit 8601b2f
Show file tree
Hide file tree
Showing 9 changed files with 206 additions and 3 deletions.
1 change: 1 addition & 0 deletions decls/i18n.js
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ declare type I18nOptions = {
modifiers?: Modifiers,
root?: I18n, // for internal
fallbackRoot?: boolean,
fallbackRootWithEmptyString?: boolean,
formatFallbackMessages?: boolean,
sync?: boolean,
silentTranslationWarn?: boolean | RegExp,
Expand Down
14 changes: 14 additions & 0 deletions gitbook/en/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,20 @@ You can specify the below some options of `I18nOptions` constructor options of [

If `false`, it's warned, and is returned the key.

#### fallbackRootWithEmptyString

> :new: 8.26+
- **Type:** `Boolean`

- **Default:** `true`

In the component localization, whether to fall back to root level (global) localization when local message is an empty string.

Please note the default behavior in vue-i18n 9.x is to not falling back to root for local message that is empty string.

If `false`, the empty local message will not fall back to root and will be kept as empty string.

#### sync

- **Type:** `Boolean`
Expand Down
8 changes: 6 additions & 2 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ export default class VueI18n {
_root: any
_sync: boolean
_fallbackRoot: boolean
_fallbackRootWithEmptyString: boolean
_localeChainCache: { [key: string]: Array<Locale>; }
_missing: ?MissingHandler
_exist: Function
Expand Down Expand Up @@ -95,6 +96,9 @@ export default class VueI18n {
this._fallbackRoot = options.fallbackRoot === undefined
? true
: !!options.fallbackRoot
this._fallbackRootWithEmptyString = options.fallbackRootWithEmptyString === undefined
? true
: !!options.fallbackRootWithEmptyString
this._formatFallbackMessages = options.formatFallbackMessages === undefined
? false
: !!options.formatFallbackMessages
Expand Down Expand Up @@ -379,7 +383,7 @@ export default class VueI18n {
}

_isFallbackRoot (val: any): boolean {
return !val && !isNull(this._root) && this._fallbackRoot
return (this._fallbackRootWithEmptyString? !val : isNull(val)) && !isNull(this._root) && this._fallbackRoot
}

_isSilentFallbackWarn (key: Path): boolean {
Expand Down Expand Up @@ -461,7 +465,7 @@ export default class VueI18n {
// We are going to replace each of
// them with its translation
const matches: any = ret.match(linkKeyMatcher)

// eslint-disable-next-line no-autofix/prefer-const
for (let idx in matches) {
// ie compatible: filter custom array
Expand Down
127 changes: 127 additions & 0 deletions test/unit/component.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -137,4 +137,131 @@ describe('component translation', () => {
vm.$destroy()
}).then(done)
})

it('fallbackRootWithEmptyString default to be true', done => {
const el = document.createElement('div')
let vm = new Vue({
i18n,
components: {
child: { // translation with component
i18n: {
locale: 'en-US',
sync: false,
messages: {
'en-US': {
who: 'child'
},
'ja-JP': {
who: '子',
}
},
},
components: {
'sub-child': { // translation with root
i18n: {
locale: 'ja-JP',
sync: false,
messages: {
'en-US': {
who: 'sub-child'
},
'ja-JP': {
who: ''
}
},
sharedMessages: { // shared messages for child1 component
'en-US': { foo: { bar: 'bar' } },
'ja-JP': { foo: { bar: 'バー' } }
}
},
render (h) {
return h('div', {}, [
h('p', { ref: 'who' }, [this.$t('who')])
])
}
}
},
render (h) {
return h('div', {}, [
h('p', { ref: 'who' }, [this.$t('who')]),
h('sub-child', { ref: 'sub-child' })
])
}
},
},
render (h) {
return h('div', {}, [
h('p', { ref: 'who' }, [this.$t('who')]),
h('child', { ref: 'child' }),
])
}
}).$mount(el)
Vue.nextTick().then(() => {
assert.strictEqual(vm.$refs.child.$refs['sub-child'].$refs.who.textContent, 'ルート')
}).then(done)
})

it('fallbackRootWithEmptyString should work when set to false', done => {
const el = document.createElement('div')
let vm = new Vue({
i18n,
components: {
child: { // translation with component
i18n: {
locale: 'en-US',
sync: false,
messages: {
'en-US': {
who: 'child'
},
'ja-JP': {
who: '子',
}
},
},
components: {
'sub-child': { // translation with root
i18n: {
locale: 'ja-JP',
sync: false,
fallbackRootWithEmptyString: false,
messages: {
'en-US': {
who: 'sub-child'
},
'ja-JP': {
who: ''
}
},
sharedMessages: { // shared messages for child1 component
'en-US': { foo: { bar: 'bar' } },
'ja-JP': { foo: { bar: 'バー' } }
}
},
render (h) {
return h('div', {}, [
h('p', { ref: 'who' }, [this.$t('who')])
])
}
}
},
render (h) {
return h('div', {}, [
h('p', { ref: 'who' }, [this.$t('who')]),
h('sub-child', { ref: 'sub-child' })
])
}
},
},
render (h) {
return h('div', {}, [
h('p', { ref: 'who' }, [this.$t('who')]),
h('child', { ref: 'child' }),
])
}
}).$mount(el)
Vue.nextTick().then(() => {
assert.strictEqual(vm.$refs.child.$refs['sub-child'].$refs.who.textContent, '')
}).then(done)
})
})
3 changes: 2 additions & 1 deletion types/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ declare namespace VueI18n {
modifiers?: Modifiers,
missing?: MissingHandler;
fallbackRoot?: boolean;
fallbackRootWithEmptyString?: boolean,
formatFallbackMessages?: boolean;
sync?: boolean;
silentTranslationWarn?: boolean | RegExp;
Expand Down Expand Up @@ -240,7 +241,7 @@ declare class VueI18n {
te(key: VueI18n.Path, locale?: VueI18n.Locale): boolean;
d(value: number | Date, key?: VueI18n.Path, locale?: VueI18n.Locale): VueI18n.DateTimeFormatResult;
d(value: number | Date, args?: { [key: string]: string }): VueI18n.DateTimeFormatResult;
d(value: number | Date, options?: VueI18n.DateTimeFormatOptions): VueI18n.DateTimeFormatResult;
d(value: number | Date, options?: VueI18n.DateTimeFormatOptions): VueI18n.DateTimeFormatResult;
n(value: number, key?: VueI18n.Path, locale?: VueI18n.Locale): VueI18n.NumberFormatResult;
n(value: number, args?: { [key: string]: string }): VueI18n.NumberFormatResult;
n(value: number, options?: VueI18n.NumberFormatOptions, locale?: VueI18n.Locale): VueI18n.NumberFormatResult;
Expand Down
14 changes: 14 additions & 0 deletions vuepress/api/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,20 @@ In the component localization, whether to fall back to root level (global) local

If `false`, it's warned, and is returned the key.

#### fallbackRootWithEmptyString

> :new: 8.26+
- **Type:** `Boolean`

- **Default:** `true`

In the component localization, whether to fall back to root level (global) localization when local message is an empty string.

Please note the default behavior in vue-i18n 9.x is to not falling back to root for local message that is empty string.

If `false`, the empty local message will not fall back to root and will be kept as empty string.

#### sync

* **Type:** `Boolean`
Expand Down
14 changes: 14 additions & 0 deletions vuepress/pt/api/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,20 @@ Ao usar a localização em componentes, determina se deve consultar a localizaç

Se definido como `false`, um aviso será lançado e uma chave retornada.

#### fallbackRootWithEmptyString

> :new: Adicionado na versão 8.26+
* **Tipo:** `Boolean`

* **Padrão:** `true`

Na localização do componente, se deve retornar à localização de nível raiz (global) quando a mensagem local for uma string vazia.

Por favor, note que o comportamento padrão no vue-i18n 9.x é não voltar ao root para a mensagem local que é uma string vazia.

Se for `false`, a mensagem local vazia não retornará ao root e será mantida como string vazia.

#### sync

* **Tipo:** `Boolean`
Expand Down
14 changes: 14 additions & 0 deletions vuepress/ru/api/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,20 @@ sidebar: auto

При значении `false` будет выбрасываться предупреждение и возвращаться ключ.

#### fallbackRootWithEmptyString

> :new: Добавлено в версии 8.26+
* **Тип:** `Boolean`

* **По умолчанию:** `true`

В локализации компонента укажите, следует ли вернуться к локализации корневого уровня (глобальной), если локальное сообщение представляет собой пустую строку.

Обратите внимание, что поведение по умолчанию в vue-i18n 9.x заключается в том, чтобы не возвращаться к корневому каталогу для локального сообщения, которое является пустой строкой.

Если `false`, пустое локальное сообщение не будет возвращено в корень и будет храниться как пустая строка.

#### sync

* **Тип:** `Boolean`
Expand Down
14 changes: 14 additions & 0 deletions vuepress/zh/api/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,20 @@ vue-i18n 版本

如果为 `false`,则会发出警告,并返回 key。

#### fallbackRootWithEmptyString

> :new: 8.26+ 新增
* **Type:** `Boolean`

* **Default:** `true`

在组件本地化中,当本地化文本为空字符串时,是否回退到根级别 (全局) 本地化。

请注意,vue-i18n 9.x版本的默认行为是对空字符串本地化文本进行回退到根级别本地化。

如果为`false`,则空的本地化文本将不会回退到根目录,并将保留为空字符串。

#### sync

* **类型:**`Boolean`
Expand Down

0 comments on commit 8601b2f

Please sign in to comment.