Skip to content

Commit

Permalink
Add support for dynamic context (#180)
Browse files Browse the repository at this point in the history
* Add support for dynamic context

* Refactor default context values.

* refactor: use immediately invoked function expression (IIFE) to improve code readibility

Co-authored-by: Cheton Wu <[email protected]>
  • Loading branch information
felixmosh and cheton authored Mar 16, 2020
1 parent 2730cd8 commit ac78ff9
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 10 deletions.
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -526,6 +526,7 @@ Below are the configuration options with their default values:
keySeparator: '.',
pluralSeparator: '_',
contextSeparator: '_',
contextDefaultValues: [],
interpolation: {
prefix: '{{',
suffix: '}}'
Expand Down Expand Up @@ -745,6 +746,13 @@ Type: `String` Default: `'_'`

The character to split context from key.

#### contextDefaultValues

Type: `Array` Default: `[]`

A list of default context values, used when the scanner encounters dynamic value as a `context`.
For a list of `['male', 'female']` the scanner will generate an entry for each value.

#### plural

Type: `Boolean` or `Function` Default: `true`
Expand Down
20 changes: 18 additions & 2 deletions src/parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ const defaults = {
context: true, // whether to add context form key
contextFallback: true, // whether to add a fallback key as well as the context form key
contextSeparator: '_', // char to split context from key
contextDefaultValues: [], // list of values for dynamic values

// Plural Form
plural: true, // whether to add plural form key
Expand Down Expand Up @@ -855,6 +856,7 @@ class Parser {
context,
contextFallback,
contextSeparator,
contextDefaultValues,
plural,
pluralFallback,
pluralSeparator,
Expand Down Expand Up @@ -927,6 +929,16 @@ class Parser {
: !!plural;
})();

const contextValues = (() => {
if (options.context !== '') {
return [options.context];
}
if (ensureArray(contextDefaultValues).length > 0) {
return ensureArray(contextDefaultValues);
}
return [];
})();

if (containsPlural) {
let suffixes = pluralFallback
? this.pluralSuffixes[lng]
Expand All @@ -938,7 +950,9 @@ class Parser {

if (containsContext && containsPlural) {
suffixes.forEach((pluralSuffix) => {
resKeys.push(`${key}${contextSeparator}${options.context}${pluralSuffix}`);
contextValues.forEach(contextValue => {
resKeys.push(`${key}${contextSeparator}${contextValue}${pluralSuffix}`);
});
});
}
} else {
Expand All @@ -947,7 +961,9 @@ class Parser {
}

if (containsContext) {
resKeys.push(`${key}${contextSeparator}${options.context}`);
contextValues.forEach(contextValue => {
resKeys.push(`${key}${contextSeparator}${contextValue}`);
});
}
}

Expand Down
4 changes: 4 additions & 0 deletions test/fixtures/context-plural.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,9 @@ i18next.t('friend', { context: 'male', count: 1 }); // output: 'A boyfriend'
i18next.t('friend', { context: 'female', count: 1 }); // output: 'A girlfriend'
i18next.t('friend', { context: 'male', count: 100 }); // output: '100 boyfriends'
i18next.t('friend', { context: 'female', count: 100 }); // output: '100 girlfriends'

i18next.t('friendWithDefaultValue', '{{count}} boyfriend', { context: 'male', count: 100 }); // output: '100 boyfriends'
i18next.t('friendWithDefaultValue', '{{count}} girlfriend', { context: 'female', count: 100 }); // output: '100 girlfriends'

i18next.t('friendDynamic', { context: dynamicVal, count: 1 });
i18next.t('friendDynamic', { context: dynamicVal, count: 100 });
1 change: 1 addition & 0 deletions test/fixtures/context.js
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
i18next.t('friend', {context: 'male'}); // output: 'A boyfriend'
i18next.t('friend', {context: 'female'}); // output: 'A girlfriend'
i18next.t('friendDynamic', {context: dynamicVal});
33 changes: 25 additions & 8 deletions test/parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -863,7 +863,8 @@ test('Context', (t) => {
translation: {
'friend': '',
'friend_male': '',
'friend_female': ''
'friend_female': '',
'friendDynamic': '',
}
}
});
Expand All @@ -888,7 +889,8 @@ test('Context', (t) => {
en: {
translation: {
'friend': '',
'friend_male': ''
'friend_male': '',
'friendDynamic': '',
}
}
});
Expand All @@ -902,7 +904,9 @@ test('Context with plural combined', (t) => {
const content = fs.readFileSync(path.resolve(__dirname, 'fixtures/context-plural.js'), 'utf-8');

test('Default options', (t) => {
const parser = new Parser();
const parser = new Parser({
contextDefaultValues: ['male', 'female'],
});
parser.parseFuncFromString(content);
t.same(parser.get(), {
en: {
Expand All @@ -918,7 +922,13 @@ test('Context with plural combined', (t) => {
'friendWithDefaultValue_male': '{{count}} boyfriend',
'friendWithDefaultValue_male_plural': '{{count}} boyfriend',
'friendWithDefaultValue_female': '{{count}} girlfriend',
'friendWithDefaultValue_female_plural': '{{count}} girlfriend'
'friendWithDefaultValue_female_plural': '{{count}} girlfriend',
'friendDynamic': '',
'friendDynamic_plural': '',
'friendDynamic_male': '',
'friendDynamic_male_plural': '',
'friendDynamic_female': '',
'friendDynamic_female_plural': '',
}
}
});
Expand All @@ -939,7 +949,8 @@ test('Context with plural combined', (t) => {
'friend_female': '',
'friendWithDefaultValue': '{{count}} boyfriend',
'friendWithDefaultValue_male': '{{count}} boyfriend',
'friendWithDefaultValue_female': '{{count}} girlfriend'
'friendWithDefaultValue_female': '{{count}} girlfriend',
'friendDynamic': '',
}
}
});
Expand All @@ -950,6 +961,7 @@ test('Context with plural combined', (t) => {
const parser = new Parser({
context: true,
contextFallback: false,
contextDefaultValues: ['male', 'female'],
plural: false
});
parser.parseFuncFromString(content);
Expand All @@ -959,7 +971,9 @@ test('Context with plural combined', (t) => {
'friend_male': '',
'friend_female': '',
'friendWithDefaultValue_male': '{{count}} boyfriend',
'friendWithDefaultValue_female': '{{count}} girlfriend'
'friendWithDefaultValue_female': '{{count}} girlfriend',
'friendDynamic_male': '',
'friendDynamic_female': '',
}
}
});
Expand All @@ -978,7 +992,9 @@ test('Context with plural combined', (t) => {
'friend': '',
'friend_plural': '',
'friendWithDefaultValue': '{{count}} boyfriend',
'friendWithDefaultValue_plural': '{{count}} boyfriend'
'friendWithDefaultValue_plural': '{{count}} boyfriend',
'friendDynamic': '',
'friendDynamic_plural': '',
}
}
});
Expand All @@ -996,7 +1012,8 @@ test('Context with plural combined', (t) => {
en: {
translation: {
'friend_plural': '',
'friendWithDefaultValue_plural': '{{count}} boyfriend'
'friendWithDefaultValue_plural': '{{count}} boyfriend',
'friendDynamic_plural': '',
}
}
});
Expand Down

1 comment on commit ac78ff9

@mohitmorepatil
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hello Team,
when i try to use context for dynamic values it does not give me expected result.I dont know if i am using the right syntax.
i am using i18n.t("friend",{context:${gender}}) where i have created state for gender const [gender,setGender]=useState("male").Can anyone help ?

Please sign in to comment.