Skip to content
This repository was archived by the owner on Dec 31, 2024. It is now read-only.

Commit bf9929c

Browse files
sebwaskazupon
authored andcommittedAug 12, 2019
⭐ new: fallback formatting (#637) by @sebwas
* Add formatting of fallback messages * Make use of (de-)activation option * Add documentation for proposed feature * 🆙 update: add getter/setter * 📝 docs: move to vuepress * 👕 refactor: update
1 parent 1cc4c72 commit bf9929c

File tree

6 files changed

+125
-1
lines changed

6 files changed

+125
-1
lines changed
 

‎decls/i18n.js

+3
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ declare type I18nOptions = {
7171
missing?: MissingHandler,
7272
root?: I18n, // for internal
7373
fallbackRoot?: boolean,
74+
formatFallbackMessages?: boolean,
7475
sync?: boolean,
7576
silentTranslationWarn?: boolean | RegExp,
7677
silentFallbackWarn?: boolean | RegExp,
@@ -106,6 +107,8 @@ declare interface I18n {
106107
set missing (handler: MissingHandler): void,
107108
get formatter (): Formatter,
108109
set formatter (formatter: Formatter): void,
110+
get formatFallbackMessages (): boolean,
111+
set formatFallbackMessages (fallback: boolean): void,
109112
get silentTranslationWarn (): boolean | RegExp,
110113
set silentTranslationWarn (silent: boolean | RegExp): void,
111114
get silentFallbackWarn (): boolean | RegExp,

‎src/index.js

+14-1
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ export default class VueI18n {
4343
_exist: Function
4444
_silentTranslationWarn: boolean | RegExp
4545
_silentFallbackWarn: boolean | RegExp
46+
_formatFallbackMessages: boolean
4647
_dateTimeFormatters: Object
4748
_numberFormatters: Object
4849
_path: I18nPath
@@ -76,6 +77,9 @@ export default class VueI18n {
7677
this._fallbackRoot = options.fallbackRoot === undefined
7778
? true
7879
: !!options.fallbackRoot
80+
this._formatFallbackMessages = options.formatFallbackMessages === undefined
81+
? false
82+
: !!options.formatFallbackMessages
7983
this._silentTranslationWarn = options.silentTranslationWarn === undefined
8084
? false
8185
: options.silentTranslationWarn
@@ -228,6 +232,9 @@ export default class VueI18n {
228232
this._vm.$set(this._vm, 'fallbackLocale', locale)
229233
}
230234

235+
get formatFallbackMessages (): boolean { return this._formatFallbackMessages }
236+
set formatFallbackMessages (fallback: boolean): void { this._formatFallbackMessages = fallback }
237+
231238
get missing (): ?MissingHandler { return this._missing }
232239
set missing (handler: MissingHandler): void { this._missing = handler }
233240

@@ -274,7 +281,13 @@ export default class VueI18n {
274281
)
275282
}
276283
}
277-
return key
284+
285+
if (this._formatFallbackMessages) {
286+
const parsedArgs = parseArgs(...values)
287+
return this._render(key, 'string', parsedArgs.params, key)
288+
} else {
289+
return key
290+
}
278291
}
279292

280293
_isFallbackRoot (val: any): boolean {

‎src/mixin.js

+1
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ export default {
3434
options.i18n.root = this.$root
3535
options.i18n.formatter = this.$root.$i18n.formatter
3636
options.i18n.fallbackLocale = this.$root.$i18n.fallbackLocale
37+
options.i18n.formatFallbackMessages = this.$root.$i18n.formatFallbackMessages
3738
options.i18n.silentTranslationWarn = this.$root.$i18n.silentTranslationWarn
3839
options.i18n.silentFallbackWarn = this.$root.$i18n.silentFallbackWarn
3940
options.i18n.pluralizationRules = this.$root.$i18n.pluralizationRules

‎test/unit/basic.test.js

+54
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,60 @@ describe('basic', () => {
161161
})
162162
})
163163

164+
describe('format arguments of fallback', () => {
165+
describe('if activated', () => {
166+
describe('named', () => {
167+
it('should return replaced string', () => {
168+
i18n = new VueI18n({
169+
locale: 'en',
170+
fallbackLocale: 'en',
171+
formatFallbackMessages: true
172+
})
173+
174+
assert.strictEqual(
175+
i18n.t('Hello {name}, how are you?', { name: 'kazupon' }),
176+
'Hello kazupon, how are you?'
177+
)
178+
})
179+
})
180+
181+
describe('list', () => {
182+
it('should return replaced string', () => {
183+
i18n = new VueI18n({
184+
locale: 'en',
185+
fallbackLocale: 'en',
186+
formatFallbackMessages: true
187+
})
188+
189+
assert.strictEqual(
190+
i18n.t('Hello {0}, how are you?', ['kazupon']),
191+
'Hello kazupon, how are you?'
192+
)
193+
})
194+
})
195+
})
196+
197+
describe('if not activated', () => {
198+
describe('named', () => {
199+
it('should not return replaced string', () => {
200+
assert.strictEqual(
201+
i18n.t('Hello {name}, how are you?', { name: 'kazupon' }),
202+
'Hello {name}, how are you?'
203+
)
204+
})
205+
})
206+
207+
describe('list', () => {
208+
it('should not return replaced string', () => {
209+
assert.strictEqual(
210+
i18n.t('Hello {0}, how are you?', ['kazupon']),
211+
'Hello {0}, how are you?'
212+
)
213+
})
214+
})
215+
})
216+
})
217+
164218
describe('locale argument', () => {
165219
it('should return empty string', () => {
166220
assert.strictEqual(i18n.t('message.hello', 'ja'), messages.ja.message.hello)

‎types/index.d.ts

+3
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ declare namespace VueI18n {
100100
formatter?: Formatter;
101101
missing?: MissingHandler;
102102
fallbackRoot?: boolean;
103+
formatFallbackMessages?: boolean;
103104
sync?: boolean;
104105
silentTranslationWarn?: boolean | RegExp;
105106
silentFallbackWarn?: boolean | RegExp;
@@ -143,6 +144,7 @@ export declare interface IVueI18n {
143144
fallbackLocale: VueI18n.Locale;
144145
missing: VueI18n.MissingHandler;
145146
formatter: VueI18n.Formatter;
147+
formatFallbackMessages: boolean;
146148
silentTranslationWarn: boolean | RegExp;
147149
silentFallbackWarn: boolean | RegExp;
148150
preserveDirectiveContent: boolean;
@@ -162,6 +164,7 @@ declare class VueI18n {
162164
fallbackLocale: VueI18n.Locale;
163165
missing: VueI18n.MissingHandler;
164166
formatter: VueI18n.Formatter;
167+
formatFallbackMessages: boolean;
165168
silentTranslationWarn: boolean | RegExp;
166169
silentFallbackWarn: boolean | RegExp;
167170
preserveDirectiveContent: boolean;

‎vuepress/guide/fallback.md

+50
Original file line numberDiff line numberDiff line change
@@ -42,3 +42,53 @@ Note, that by default falling back to `fallbackLocale` generates two console war
4242
```
4343

4444
To suppress these warnings (while keeping those which warn of the total absence of translation for the given key) set `silentFallbackWarn: true` when initializing the `VueI18n` instance.
45+
46+
## Fallback interpolation
47+
48+
Since the keys to the translations are strings, the original message can be used as a key instead of the path.
49+
E.g.
50+
51+
```javascript
52+
const messages = {
53+
ja: {
54+
'Hello world': 'こんにちは、世界'
55+
}
56+
}
57+
```
58+
59+
This way the translations can be used in a very natural way, automatically falling back to the source language if the translated string cannot be found:
60+
61+
```html
62+
<p>{{ $t('Hello world') }}</p>
63+
```
64+
65+
To enrich this feature, interpolation of fallback messages can be turned on by setting `formatFallbackMessages` to `true`:
66+
67+
```javascript
68+
const messages = {
69+
ru: {
70+
'Hello {name}': 'Здравствуйте {name}'
71+
}
72+
}
73+
74+
const i18n = new VueI18n({
75+
locale: 'ru',
76+
fallbackLocale: 'en',
77+
formatFallbackMessages: true,
78+
messages
79+
})
80+
```
81+
82+
When you template the below:
83+
84+
```html
85+
<p>{{ $t('Hello {name}', { name: 'John' }}) }}</p>
86+
<p>{{ $t('The weather today is {condition}!', { condition: 'sunny' }) }}</p>
87+
```
88+
89+
The following will be the output:
90+
91+
```html
92+
<p>Здравствуйте John</p>
93+
<p>The weather today is sunny!</p>
94+
```

0 commit comments

Comments
 (0)
This repository has been archived.