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

Commit b9437ea

Browse files
Raiondesukazupon
authored andcommitted
⚡ improvement(format): Add the path as argument to the custom formatter (#489) by @Raiondesu
* ⚡improvement(types): typed autocomplete in date and number format options Replace Number and Date format options with standard TS `Intl` types, while also adding guiding TS autocomplete to them. This change exterminates the confusion of which types to follow, while preserving backwards-compatibility for types and adding optional autocomplete. * ⚡improvement(types/test): add type constraints to format options It's useful to check static variables types whenever possible. * ⚡new(formatter): add path to the formatter arguments and allow optional formatting * ⚡improvement(types): backward-compatibility for #484 * 📃docs(formatter): add case for the undefined return type * ⚡improvement(types): include the possible undefined return type * ✅tests(issues): make formatter return undefined in test for #484 * update(formatter): change default foramtter invocation from undefined to null
1 parent 439ed69 commit b9437ea

5 files changed

Lines changed: 49 additions & 8 deletions

File tree

decls/i18n.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,5 +110,5 @@ declare interface I18n {
110110
};
111111

112112
declare interface Formatter {
113-
interpolate (message: string, values?: any): Array<any>
113+
interpolate (message: string, values: any, path: string): (Array<any> | null)
114114
};

gitbook/en/formatting.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,12 +157,17 @@ class CustomFormatter {
157157
// -> passed values: Array (included VNode):
158158
// `[VNode{ tag: 'p', text: 'kazupon', ...}, VNode{ tag: 'p', text: 'how are you?', ...}]`
159159
//
160+
// @param {string} path
161+
// a path to the message, as passed into the $t/t() functions.
162+
// - $t('hello.louis') -> path === 'hello.louis'
163+
//
160164
// @return {Array<any>}
161165
// interpolated values. you need to return the following:
162166
// - array of string, when is using `$t` or `$tc`.
163167
// - array included VNode object, when is using `i18n` functional component.
168+
// - null - if you want the default vue-i18n formatter to handle the case
164169
//
165-
interpolate (message, values) {
170+
interpolate (message, values, path) {
166171
// implement interpolation logic here
167172
// ...
168173

src/index.js

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ const formatters = {
3737
'lower': (str) => str.toLocaleLowerCase()
3838
}
3939

40+
const defaultFormatter = new BaseFormatter()
41+
4042
export default class VueI18n {
4143
static install: () => void
4244
static version: string
@@ -76,7 +78,7 @@ export default class VueI18n {
7678
const numberFormats = options.numberFormats || {}
7779

7880
this._vm = null
79-
this._formatter = options.formatter || new BaseFormatter()
81+
this._formatter = options.formatter || defaultFormatter
8082
this._missing = options.missing || null
8183
this._root = options.root || null
8284
this._sync = options.sync === undefined ? true : !!options.sync
@@ -246,7 +248,7 @@ export default class VueI18n {
246248
ret = this._link(locale, message, ret, host, interpolateMode, values, visitedLinkStack)
247249
}
248250

249-
return this._render(ret, interpolateMode, values)
251+
return this._render(ret, interpolateMode, values, key)
250252
}
251253

252254
_link (
@@ -322,9 +324,15 @@ export default class VueI18n {
322324
return ret
323325
}
324326

325-
_render (message: string, interpolateMode: string, values: any): any {
326-
const ret = this._formatter.interpolate(message, values)
327-
// if interpolateMode is **not** 'string' ('raw'),
327+
_render (message: string, interpolateMode: string, values: any, path: string): any {
328+
let ret = this._formatter.interpolate(message, values, path)
329+
330+
// If the custom formatter refuses to work - apply the default one
331+
if (!ret) {
332+
ret = defaultFormatter.interpolate(message, values, path)
333+
}
334+
335+
// if interpolateMode is **not** 'string' ('row'),
328336
// return the compiled data (e.g. ['foo', VNode, 'bar']) with formatter
329337
return interpolateMode === 'string' ? ret.join('') : ret
330338
}

test/unit/issues.test.js

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -630,4 +630,32 @@ describe('issues', () => {
630630
VueI18n.prototype.getChoiceIndex = defaultImpl
631631
})
632632
})
633+
634+
describe('#484', () => {
635+
it('passes path to the formatter', () => {
636+
const testPath = 'test.deep.message'
637+
638+
i18n = new VueI18n({
639+
locale: 'en',
640+
messages: {
641+
en: {
642+
test: {
643+
deep: {
644+
message: 'Hello!'
645+
}
646+
}
647+
}
648+
},
649+
formatter: {
650+
interpolate (message, values, path) {
651+
assert(path, testPath)
652+
653+
return null // pass the case to the default formatter
654+
}
655+
}
656+
})
657+
658+
assert(i18n.t(testPath), 'Hello!')
659+
})
660+
})
633661
})

types/index.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ declare namespace VueI18n {
7070
};
7171

7272
interface Formatter {
73-
interpolate(message: string, values?: Values): any[];
73+
interpolate(message: string, values: Values | undefined, path: string): (any[] | null);
7474
}
7575

7676
type MissingHandler = (locale: Locale, key: Path, vm?: Vue) => string | void;

0 commit comments

Comments
 (0)