Skip to content

Commit

Permalink
⭐ new: Add constructor option for custom modifiers (#724) by @epaezrubio
Browse files Browse the repository at this point in the history


* Add constructor option for custom modifiers

* Add modifiers typescript definitions

* Add documentation for modifiers
  • Loading branch information
epaezrubio authored and kazupon committed Oct 14, 2019
1 parent e0fbaaa commit 3217212
Show file tree
Hide file tree
Showing 10 changed files with 87 additions and 6 deletions.
2 changes: 2 additions & 0 deletions decls/i18n.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ declare type NumberFormatOptions = {
};
declare type NumberFormat = { [key: string]: NumberFormatOptions };
declare type NumberFormats = { [key: Locale]: NumberFormat };
declare type Modifiers = { [key: string]: (str : string) => string };

declare type TranslateResult = string | LocaleMessages;
declare type DateTimeFormatResult = string;
Expand All @@ -69,6 +70,7 @@ declare type I18nOptions = {
numberFormats?: NumberFormats,
formatter?: Formatter,
missing?: MissingHandler,
modifiers?: Modifiers,
root?: I18n, // for internal
fallbackRoot?: boolean,
formatFallbackMessages?: boolean,
Expand Down
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion src/components/interpolation.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ function onlyHasDefaultPlace (params) {

function useLegacyPlaces (children, places) {
const params = places ? createParamsFromPlaces(places) : {}

if (!children) { return params }

// Filter empty text nodes
Expand Down
11 changes: 8 additions & 3 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ const htmlTagMatcher = /<\/?[\w\s="/.':;#-\/]+>/
const linkKeyMatcher = /(?:@(?:\.[a-z]+)?:(?:[\w\-_|.]+|\([\w\-_|.]+\)))/g
const linkKeyPrefixMatcher = /^@(?:\.([a-z]+))?:/
const bracketsMatcher = /[()]/g
const formatters = {
const defaultModifiers = {
'upper': str => str.toLocaleUpperCase(),
'lower': str => str.toLocaleLowerCase()
}
Expand All @@ -36,6 +36,7 @@ export default class VueI18n {

_vm: any
_formatter: Formatter
_modifiers: Modifiers
_root: any
_sync: boolean
_fallbackRoot: boolean
Expand Down Expand Up @@ -71,6 +72,7 @@ export default class VueI18n {

this._vm = null
this._formatter = options.formatter || defaultFormatter
this._modifiers = options.modifiers || {}
this._missing = options.missing || null
this._root = options.root || null
this._sync = options.sync === undefined ? true : !!options.sync
Expand Down Expand Up @@ -418,8 +420,11 @@ export default class VueI18n {
locale, linkPlaceholder, translated, host,
Array.isArray(values) ? values : [values]
)
if (formatters.hasOwnProperty(formatterName)) {
translated = formatters[formatterName](translated)

if (this._modifiers.hasOwnProperty(formatterName)) {
translated = this._modifiers[formatterName](translated)
} else if (defaultModifiers.hasOwnProperty(formatterName)) {
translated = defaultModifiers[formatterName](translated)
}

visitedLinkStack.pop()
Expand Down
9 changes: 8 additions & 1 deletion test/unit/basic.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@ describe('basic', () => {
i18n = new VueI18n({
locale: 'en',
fallbackLocale: 'en',
messages
messages,
modifiers: {
custom: str => str.replace(/[aeiou]/g, 'x')
}
})
})

Expand Down Expand Up @@ -57,6 +60,10 @@ describe('basic', () => {
it('should translate link without formatting if modifier is not known.', () => {
assert.strictEqual(i18n.t('message.linkCaseUnknown'), 'Home address')
})

it('should render link with custom formatting.', () => {
assert.strictEqual(i18n.t('message.linkCaseCustom'), 'Hxmx xddrxss')
})
})

describe('ja locale', () => {
Expand Down
1 change: 1 addition & 0 deletions test/unit/fixture/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export default {
linkCaseLower: 'Please provide @.lower:message.homeAddress',
linkCaseUpper: '@.upper:message.homeAddress',
linkCaseUnknown: '@.unknown:message.homeAddress',
linkCaseCustom: '@.custom:message.homeAddress',
homeAddress: 'Home address',
circular1: 'Foo @:message.circular2',
circular2: 'Bar @:message.circular3',
Expand Down
2 changes: 2 additions & 0 deletions types/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ declare namespace VueI18n {
*/
[lang: string]: (choice: number, choicesLength: number) => number;
};
type Modifiers = { [key: string]: (str : string) => string };

type FormattedNumberPartType = 'currency' | 'decimal' | 'fraction' | 'group' | 'infinity' | 'integer' | 'literal' | 'minusSign' | 'nan' | 'plusSign' | 'percentSign';

Expand Down Expand Up @@ -98,6 +99,7 @@ declare namespace VueI18n {
dateTimeFormats?: DateTimeFormats;
numberFormats?: NumberFormats;
formatter?: Formatter;
modifiers?: Modifiers,
missing?: MissingHandler;
fallbackRoot?: boolean;
formatFallbackMessages?: boolean;
Expand Down
3 changes: 3 additions & 0 deletions types/test/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,9 @@ const i18n = new VueI18n({
return [message];
},
},
modifiers: {
foo: (str) => 'bar'
},
missing(locale, key, vm) {
},
fallbackRoot: false,
Expand Down
10 changes: 10 additions & 0 deletions vuepress/api/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,16 @@ The list of available locales in `messages` in lexical order.

The formatter that implemented with `Formatter` interface.

#### modifiers

> :new: 8.15.0+
* **Type:** `Modifier`

* **Default:** `lower` and `upper` modifiers

Modifiers functions for linked messages

#### missing

* **Type:** `MissingHandler`
Expand Down
51 changes: 51 additions & 0 deletions vuepress/guide/messages.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,57 @@ Output:
<p>DIO: the world !!!!</p>
```

### Formatting linked locale messages

If the language distinguish cases of character, you may need control the case of the linked locale messages.
Linked messages can be formatted with modifier `@.modifier:key`

The below modifiers are available currently.

* `upper`: Uppercase all characters in the linked message.
* `lower`: Lowercase all characters in the linked message.

Locale messages the below:

```javascript
const messages = {
en: {
message: {
homeAddress: 'Home address',
missingHomeAddress: 'Please provide @.lower:message.homeAddress'
}
}
}
```

```html
<label>{{ $t('message.missingHomeAddress') }}</label>

<p class="error">{{ $t('message.missingHomeAddress') }}</p>
```

Output the below:

```html
<label>Home address</label>

<p class="error">Please provide home address</p>
```

You can add modifiers or overwrite the existing ones passing the `modifiers` options to the `VueI18n` constructor.

```javascript
const i18n = new VueI18n({
locale: 'en',
messages: {
// ...
},
modifiers: {
snakeCase: (str) => str.split(' ').join('-')
}
})
```


### Grouping by brackets

Expand Down

0 comments on commit 3217212

Please sign in to comment.