Describe the bug
Nested HTML element within Trans seems like not working
Occurs in react-i18next version
10.11.3
To Reproduce
Steps to reproduce the behavior:
i have this
<Trans i18nKey={"Are you sure you want to <0>delete</0> account <0><1>{{name}}</1></0> ?"} values={{name}} components={[<b key={0} />, <i key={1} />]} >
</Trans>
{{name}} should be bold then italic, however, it becomes simply not shown.
Does not work this way...inner <0><1> -> <1> must be inside b it's nesting not replacing by number
<Trans i18nKey={"Are you sure you want to <0>delete</0> account <1>{{name}}</1> ?"} values={{name}} components={[<b key={0} />, <b><i key={1} /></b>]} >
</Trans>
@jamuhl I'm facing a similar problem, and I still don't understand how to properly use the components array, if they don't work by replacing the equivalent numbered tag. The documentation is not clear on this.
I need to map a large array of translations, with varying nesting of elements, and tried do something similar to this:
const keys = [
'test1', // "<0>Text inside paragraph</0>"
'test2', // "<0>Text inside paragraph with <1>bold text</1></0>",
'test3', // "just some <1>bold text</1>",
'test4' // "<0>Text inside paragraph with <3>a link</3> for the user</0>"
]
// ...
<ul>
{keys.map(key => (
<li key={key}>
<Trans
i18nKey={key}
components={[<p />, <strong />, <a href='#'></a>]}
/>
</li>
))}
</ul>
Expected output:
<ul>
<li>
<p>Text inside paragraph</p>
</li>
<li>
<p>Text inside paragraph with <strong>bold text</strong></p>
</li>
<li>just some <strong>bold text</strong></li>
<li>
<p>Text inside paragraph with <a href='#'>a link</a> for the user</p>
</li>
</ul>
Actual output:
<ul>
<li>
<p>Text inside paragraph</p>
</li>
<li>
<p></p>
</li>
<li>just some <strong>bold text</strong></li>
<li>
<p></p>
</li>
</ul>
How could I achieve the "expected" output using the <Trans> component, or by any other means in react-i18next?
@tisoap the problem is when you got nested numbers <0> hi <0>strong</0></0> it expects components={[<span><strong></strong></span>]} <- the nesting is also here
basically the same as:
<Trans><span>hello <strong>world</strong></span></Trans> // --> with a slightly difference in inner index the string would be -> <0> hi <1>strong</1></0>
Oh, now I finally understand how the components prop works! For future readers reference, this is how I could have written my example above to get the expected results:
const keys = [
'test1', // "<0>Text inside paragraph</0>"
'test2', // "<0>Text inside paragraph with <0>bold text</0></0>",
'test3', // "just some <1>bold text</1>",
'test4' // "<0>Text inside paragraph with <1>a link</1> for the user</0>"
]
// ...
<ul>
{keys.map(key => (
<li key={key}>
<Trans
i18nKey={key}
components={[
// index 0
<p>
{ /* New nesting level means the index starts over */ }
<strong /> { /* index 0 */ }
<a href='#' /> { /* index 1 */ }
</p>,
// index 1
<strong />
]}
/>
</li>
))}
</ul>
But to be fair, this is a rather confusing API, that yields an awkward components prop declaration and hard to maintain translation texts like <0><0><0>this</0></0></0>.
I see there's already some ongoing discussion at #833 to allow for named placeholders by passing an object to components prop, which would help a lot.
In my opinion, making the numbered placeholders match the equivalent position in the components array would be a more intuitive API than having to track nesting levels.
But more importantly, how to use <Trans> with nested components should definitely be in the documentation.
@tisoap the main use case was always using Trans children...using components was just a fallback for the devs using ICU...but agree with you things can be improved:
Yes, I'll try to tackle those on my spare time!
"<0>Text inside paragraph with <0>bold text</0></0>",
Wouldn't that one be <1>bold text</1> as there is text before it? 馃
@DominicTobias-b1
<Trans
i18nKey={key}
components={[
// index 0
<p>
{ /* New nesting level means the index starts over */ }
<strong /> { /* index 0 */ }
<a href='#' /> { /* index 1 */ }
</p>,
// index 1
<strong />
]}
/>
The JSX has no text in front...if so - yes would be <1>
Most helpful comment
But to be fair, this is a rather confusing API, that yields an awkward
componentsprop declaration and hard to maintain translation texts like<0><0><0>this</0></0></0>.I see there's already some ongoing discussion at #833 to allow for named placeholders by passing an object to
componentsprop, which would help a lot.In my opinion, making the numbered placeholders match the equivalent position in the
componentsarray would be a more intuitive API than having to track nesting levels.But more importantly, how to use
<Trans>with nested components should definitely be in the documentation.