Skip to content

Commit 31f0d2e

Browse files
committed
<Trans count> prop: optional - infer count from children #1891
1 parent ba89d1d commit 31f0d2e

File tree

5 files changed

+104
-1
lines changed

5 files changed

+104
-1
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
### 16.4.0
2+
3+
- `<Trans count>` prop: optional - infer count from children [1891](https://github.com/i18next/react-i18next/issues/1891)
4+
15
### 16.3.5
26

37
- fix runaway effect in useTranslation [1888](https://github.com/i18next/react-i18next/issues/1888) by [1889](https://github.com/i18next/react-i18next/pull/1889)

react-i18next.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2441,6 +2441,19 @@
24412441
newTarget.props = Object.assign(source.props, target.props);
24422442
return newTarget;
24432443
};
2444+
const getValuesFromChildren = children => {
2445+
const values = {};
2446+
if (!children) return values;
2447+
const getData = childs => {
2448+
const childrenArray = getAsArray(childs);
2449+
childrenArray.forEach(child => {
2450+
if (isString(child)) return;
2451+
if (hasChildren(child)) getData(getChildren(child));else if (isObject(child) && !React.isValidElement(child)) Object.assign(values, child);
2452+
});
2453+
};
2454+
getData(children);
2455+
return values;
2456+
};
24442457
const nodesToString = (children, i18nOptions, i18n, i18nKey) => {
24452458
if (!children) return '';
24462459
let stringNode = '';
@@ -2753,6 +2766,10 @@
27532766
...i18n.options.interpolation.defaultVariables
27542767
};
27552768
}
2769+
const valuesFromChildren = getValuesFromChildren(children);
2770+
if (valuesFromChildren && typeof valuesFromChildren.count === 'number' && count === undefined) {
2771+
count = valuesFromChildren.count;
2772+
}
27562773
const interpolationOverride = values || count !== undefined && !i18n.options?.interpolation?.alwaysFormat || !children ? tOptions.interpolation : {
27572774
interpolation: {
27582775
...tOptions.interpolation,

react-i18next.min.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/TransWithoutContext.js

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,21 @@ const mergeProps = (source, target) => {
3030
return newTarget;
3131
};
3232

33+
const getValuesFromChildren = (children) => {
34+
const values = {};
35+
if (!children) return values;
36+
const getData = (childs) => {
37+
const childrenArray = getAsArray(childs);
38+
childrenArray.forEach((child) => {
39+
if (isString(child)) return;
40+
if (hasChildren(child)) getData(getChildren(child));
41+
else if (isObject(child) && !isValidElement(child)) Object.assign(values, child);
42+
});
43+
};
44+
getData(children);
45+
return values;
46+
};
47+
3348
export const nodesToString = (children, i18nOptions, i18n, i18nKey) => {
3449
if (!children) return '';
3550
let stringNode = '';
@@ -530,6 +545,14 @@ export function Trans({
530545
? { ...values, ...i18n.options.interpolation.defaultVariables }
531546
: { ...i18n.options.interpolation.defaultVariables };
532547
}
548+
549+
const valuesFromChildren = getValuesFromChildren(children);
550+
551+
if (valuesFromChildren && typeof valuesFromChildren.count === 'number' && count === undefined) {
552+
// eslint-disable-next-line no-param-reassign
553+
count = valuesFromChildren.count;
554+
}
555+
533556
const interpolationOverride =
534557
values ||
535558
(count !== undefined && !i18n.options?.interpolation?.alwaysFormat) || // https://github.com/i18next/react-i18next/issues/1719 + https://github.com/i18next/react-i18next/issues/1801

test/trans.render.spec.jsx

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -385,6 +385,65 @@ describe('trans complex - count only in props', () => {
385385
});
386386
});
387387

388+
describe('trans complex - count inferred from children', () => {
389+
function TestComponent() {
390+
const count = 10;
391+
const name = 'Jan';
392+
// prettier-ignore
393+
return (
394+
<Trans i18nKey="transTest2">
395+
Hello <strong>{{ name }}</strong>, you have {{ count }} message. Open <Link to="/msgs">here</Link>.
396+
</Trans>
397+
);
398+
}
399+
400+
it('should render correct content', () => {
401+
const { container } = render(<TestComponent />);
402+
expect(container.firstChild).toMatchInlineSnapshot(`
403+
<div>
404+
Hello
405+
<strong>
406+
Jan
407+
</strong>
408+
, you have
409+
10
410+
messages. Open
411+
<a
412+
href="/msgs"
413+
>
414+
here
415+
</a>
416+
.
417+
</div>
418+
`);
419+
});
420+
});
421+
422+
describe('trans with count and stuff inferred', () => {
423+
function TestComponent() {
424+
const count = 123;
425+
const stuff = 'hey';
426+
return (
427+
<Trans>
428+
<strong>
429+
{{ count }} and {{ stuff }}
430+
</strong>
431+
</Trans>
432+
);
433+
}
434+
435+
it('should render correct content', () => {
436+
const { container } = render(<TestComponent />);
437+
expect(container.firstChild).toMatchInlineSnapshot(`
438+
<div>
439+
<strong>
440+
123 and hey
441+
</strong>
442+
</div>
443+
`);
444+
});
445+
});
446+
388447
describe('trans complex v2 no extra pseudo elements for interpolation', () => {
389448
function TestComponent() {
390449
const count = 10;

0 commit comments

Comments
 (0)