Skip to content

Commit

Permalink
feat(parser): Handle a few more use cases of potential count attribut…
Browse files Browse the repository at this point in the history
…es. (#260)
  • Loading branch information
vincentdesmares authored Jun 14, 2024
1 parent 19c9fca commit 985e6de
Show file tree
Hide file tree
Showing 3 changed files with 129 additions and 5 deletions.
22 changes: 22 additions & 0 deletions src/parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -614,6 +614,28 @@ class Parser {
}, {});
}

// Member Expression (e.g. i18nKey={foo.bar})
if (expression.type === 'MemberExpression') {
acc[name] = expression.object.name + '.' + expression.property.name;
}

// Conditional Expression (e.g. i18nKey={true ? 'foo' : 'bar'})
if (expression.type === 'ConditionalExpression') {
acc[name] = expression.consequent.value;
}

// Unary Expression (e.g. i18nKey={foo?.bar})
if (expression.type === 'UnaryExpression') {
acc[name] = expression.alternate.object.name + '.' + expression.alternate.property.name;
}

// Binary Expression (e.g. i18nKey={foo.bar - 1})
if (expression.type === 'BinaryExpression') {
if (expression.left.type === 'MemberExpression' && expression.right.type === 'Literal') {
acc[name] = expression.left.object.name + '.' + expression.left.property.name;
}
}

// Template Literal
if (expression.type === 'TemplateLiteral') {
acc[name] = expression.quasis
Expand Down
6 changes: 5 additions & 1 deletion test/react-i18next/i18n.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ i18n.init({
transTest2InV2: 'Hello <1>{{name}}</1>, you have {{count}} message. Open <5>hear</5>.',
transTest2InV2_other:
'Hello <1>{{name}}</1>, you have {{count}} messages. Open <5>here</5>.',
transPluralWithCountAsMemberExpression: '{{count}} item',
transPluralWithCountAsMemberExpression_other: '{{count}} items',
testTransKey1: '<0>{{numOfItems}}</0> item matched.',
testTransKey1_other: '<0>{{numOfItems}}</0> items matched.',
testTransKey2: '<0><0>{{numOfItems}}</0></0> item matched.',
Expand All @@ -53,7 +55,9 @@ i18n.init({
escapeValue: false, // not needed for react!!
formatSeparator: ',',
format(value, format) {
if (format === 'uppercase') return value.toUpperCase();
if (format === 'uppercase') {
return value.toUpperCase();
}
return value;
},
},
Expand Down
106 changes: 102 additions & 4 deletions test/react-i18next/trans-render.test.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/** @jest-environment jsdom */
import React from 'react';
import { render } from '@testing-library/react';
import React from 'react';
import {
Trans,
withTranslation,
Expand Down Expand Up @@ -309,7 +309,7 @@ describe('trans complex - count only in props', () => {
// prettier-ignore
return (
<Trans i18nKey="transTest2" count={count}>
Hello <strong>{{ name }}</strong>, you have {{n: count}} message. Open <Link to="/msgs">here</Link>.
Hello <strong>{{ name }}</strong>, you have {{ n: count }} message. Open <Link to="/msgs">here</Link>.
</Trans>
);
};
Expand Down Expand Up @@ -368,10 +368,108 @@ describe('trans complex v2 no extra pseudo elements for interpolation', () => {
});
});

describe('Trans with a count using an object property should be detected as a translation with a plural', () => {
const TestComponent = () => {
const obj = { anyProp: { a: 10 } };
// prettier-ignore
return (
<Trans
i18nKey="transPluralWithCountAsMemberExpression"
count={obj.anyProp.a}
>
{{ count: obj.anyProp }} item.
</Trans>
);
};

it('should render correct content with the count', () => {
const { container } = render(<TestComponent />);
expect(container.firstChild).toMatchInlineSnapshot(`
<div>
10 items
</div>
`);
});
});

describe('Trans with a count using an conditionnal statement should be detected as a translation with a plural', () => {
const TestComponent = () => {
const obj = true;
// prettier-ignore
return (
<Trans
i18nKey="transPluralWithCountAsMemberExpression"
count={obj ? 3 : 10}
>
{{ count: 6 }} item.
</Trans>
);
};

it('should render correct content with the count', () => {
const { container } = render(<TestComponent />);
expect(container.firstChild).toMatchInlineSnapshot(`
<div>
3 items
</div>
`);
});
});

describe('Trans with a count using an Unary Expression statement should be detected as a translation with a plural', () => {
const TestComponent = () => {
const obj = { a: 3 };
// prettier-ignore
return (
<Trans
i18nKey="transPluralWithCountAsMemberExpression"
count={obj?.a}
>
{{ count: 6 }} item.
</Trans>
);
};

it('should render correct content with the count', () => {
const { container } = render(<TestComponent />);
expect(container.firstChild).toMatchInlineSnapshot(`
<div>
3 items
</div>
`);
});
});

describe('Trans with a count using an Binary Expression statement should be detected as a translation with a plural', () => {
const TestComponent = () => {
const obj = { a: 3 };
// prettier-ignore
return (
<Trans
i18nKey="transPluralWithCountAsMemberExpression"
count={obj.a - 1}
>
{{ count: 6 }} item.
</Trans>
);
};

it('should render correct content with the count', () => {
const { container } = render(<TestComponent />);
expect(container.firstChild).toMatchInlineSnapshot(`
<div>
2 items
</div>
`);
});
});

describe('trans with t as prop', () => {
const TestComponent = ({ t, cb }) => {
const customT = (...args) => {
if (cb) cb();
if (cb) {
cb();
}
return t(...args);
};
return (
Expand Down Expand Up @@ -415,7 +513,7 @@ describe('trans with empty content', () => {
const TestComponent = () => <Trans />;
it('should render an empty string', () => {
const { container } = render(<TestComponent />);
expect(container.firstChild).toMatchInlineSnapshot(`<div />`);
expect(container.firstChild).toMatchInlineSnapshot('<div />');
});
});

Expand Down

0 comments on commit 985e6de

Please sign in to comment.