Hi there! First of all, thank you for all the work you put into i18next! It is by far the best i18n lib we've come across, and it just keeps getting better and better :)
Is your feature request related to a problem? Please describe.
I'm running into some issues with the numeric (<0>) placeholders in the <Trans components={[...]} /> prop.
First of all, the translation tool we use has first-class support for html placeholders, meaning that during the translation process they automatically get detected and copied to the target translation. Without a mechanism like this you very quickly run into awkward scenarios with for example RTL input. However, this detection is built on top of an X(HT)ML parser, and the XML spec dictates that tags are only valid if they start with a letter. As a result the numeric <0> placeholders are not picked up and the detection does not work in this case.
Secondly, I'm noticing that numeric placeholders sometimes convey too little context to translators. Given the following 2 strings:
<0>{{firstName}} {{lastName}}</0> added a new <1>comment</1> to article <2>{{articleTitle}}</2><profileLink>{{firstName}} {{lastName}}</profileLink> added a new <commentLink>comment</commentLink> to article <articleLink>{{articleTitle}}</articleLink>I personally prefer the latter one. It's a bit more verbose, but verbosity is important when involving external translators into a project as they need additional context to figure out what is what. In addition, it looks more familiar to html which they generally already have some notion of, + it's a bit more resilient to change as it doesn't rely on order.
Describe the solution you'd like
I was wondering if you'd be open to support a secondary object syntax for the components prop, i.e.:
<Trans
i18nKey="myKey"
components={{
articleLink: <a href="..." />,
commentlink: <a href="..." />,
profileLink: <a href="..." />
}}
values={values}
/>
Which would enable the use of the "named placeholder" method above. I can have a stab at this myself, just will have to dig into the Trans component a bit first :)
Will need to think about it...got a little mixed feeling about adding complexity...might be something for a custom component...not yet sure.
Beside that -> you should use https://locize.com to support us - that's our TM solution: https://www.youtube.com/watch?v=9NOzJhgmyQE
The very big advantage of this is also you need to pass children for Trans currently, which I find really problematic. For instance thing like:
<Trans i18nKey="dragOrPickFromDisk">
Drag or
<Button>
pick from disk
</Button>
</Trans>
Several problems with this:
dragOrPickFromDisk should be all it needs plus object of components to be injectedCompare it with this:
<Trans
i18nKey="dragOrPickFromDisk"
components={{ button: <Button />}}
/>
Advantage is cleaner jsx, less duplication, plus it would be easy to use interpolations in translations, as u would not use indexes of components anymore, but keys
@klis87 matter of taste - like said...additional options add complexity (not only in the code - but in documentation and adaption too).
Open for a PR - but will decide after seeing the implementation if this could be accepted.
@klis87 duplication can be avoided.
"react-i18next": "^10.8.1",
<Trans i18nKey="test" components={[<Link to="/" />]} />
md5-2642b190844494609564ca699615ecee
```html
You can <a href="/">navigate to the home page</a> or use the main menu links.
md5-dae9745e49954339ac6d5e2476d0838f
```json
{
"test": "You should agree <terms>our terms</terms> and <policy>our policy</policy>"
}
@iamandrewluca awesome! I did not know it was added in version 10!
As I investigated, mapAST is responsible for mapping, but it's a bit overcomplicated, it needs some core devs intervention I think. Or I'll give one more try. That if/else pyramid should be flattened :smile:
I would also really like this feature. The values prop allows for a key identifier to be specified, so why not also allow this for components?
For my use case:
Many of the translation entries in my json file look like this:
"key": "Don't have an account? <1>Click to register!</1>
With the following code in my React component:
<Trans components={[null, <a href='/register' /> ]}>key</Trans>
I now have to specify null everywhere as the first entry of the array. This gets worse with multiple interpolated components (for every piece of text between components I have to specify a null object in the array.
When objects in component are supported, I could simply specify the key as the property name, like this:
"key": "Don't have an account? <registerLink>Click to register!</registerLink>
<Trans components={{registerLink: <a href='/register' />}}>key</Trans>
Or maybe even like this, if you don't like the idea of a named key:
"key": "Don't have an account? <1>Click to register!</1>
<Trans components={{1: <a href='/register' />}}>key</Trans>
@nphmuller https://github.com/i18next/react-i18next/pull/859 not sure but that PR "just" misses the tests.
@jamuhl That's great to hear. But I just figured out a mistake I made in the samples I posted. So the feature is not necessary anymore for my use case.
I you like at the examples I posted, the <a> tags all are replaced with <1> in the translation file. I thought that was necessary when looking at the documentation, because the text before it would count as <0>. I just figured out however that if I use the components prop, I can define them as <0>, and everything still works. That way I don't need the null value in the array for the components prop anymore! :)
@nphmuller waiting for this to be merged https://github.com/rayd/html-parse-stringify2/pull/20, and I'll add tests and finish that PR
I have a key like Enter a URL to send it as a simple message to other users by click on the {{videoIcon}} icon. and value also same in en.json. But trying to use
<Trans
i18nKey="Enter a URL to send it as a simple message to other users by click on the {{videoIcon}} icon."
components={{ videoIcon: <VideoIcon /> }}
/>
But this is rendered as
Enter a URL to send it as a simple message to other users by click on the [object Object] icon.
Please suggest how to use in this case.
@raghuprathap that does not work like this...read: https://react.i18next.com/latest/trans-component#alternative-usage components is an array and not a named interpolation value
@raghuprathap right now this is supported only
<Trans
i18nKey="Enter a URL to send it as a simple message to other users by click on the <0/> icon."
components={[<VideoIcon />]}
/>
@iamandrewluca I have a similar issue and cant seem to get Trans to work. Been at it for a couple hours now.
<Trans i18nKey="navbar.poweredBy" components={[<Link to="/" style={{ color: 'white' }}>Disney</Link>]} />
poweredBy: "Powered by <0/>"
It just prints Powered by, theres no Disney...
@robinsingh-bw did you try:
poweredBy: "Powered by <0>Disney</0>" ?
@jamuhl I just tried that too, still nothing
Gatsby was caching the translation files so no matter what I did it just wouldn't work. Clearing the cache solved it. You don't happen to know how to avoid caching translation files in gatsby by any chance? :p
@robinsingh-bw sorry but no - I got no idea how to do that...would love to have the time to put up a sample with gatsby. Doing things the right way - like prerendering all languages to static files in separated folders - honestly always hoped the community will come up with something similar to next-i18next for gatsby...but seems not...
This actually extends beyond a nice-to-have. Correct me if I'm wrong, but in cases where the translation's components change order between languages, the index-based solution doesn't work.
For example:
The current case
en/common.json
{ "test": "This is a test translation where <1>ordering changes between languages</1>." }
fr/common.json
{ "test": "<0>Le this is a test translation</0> where ordering changes between languages." }
<Trans i18nKey="test" components={[<b></b>]} />
This result is that en fails to insert the component properly.
Proposed solution
en/common.json
{ "test": "This is a test translation where <bolded>ordering changes between languages</bolded>."}
fr/common.json
{ "test": "<bolded>Le this is a test translation</bolded> where ordering changes between languages." }
<Trans i18nKey="test" components={{ bolded: <b></b> }} />
@rubystephenpoole no...<0> references the first item in the components array...nothing todo with the position in the translation string -> in your sample en sample is wrong...should be { "test": "This is a test translation where <0>ordering changes between languages</0>." }
Thanks for the clarification.
On Oct 23, 2019, at 5:08 PM, Jan Mühlemann notifications@github.com wrote:
@rubystephenpoole https://github.com/rubystephenpoole no...<0> references the first item in the components array...nothing todo with the position in the translation string -> in your sample en sample is wrong...should be { "test": "This is a test translation where <0>ordering changes between languages0>." }
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub https://github.com/i18next/react-i18next/issues/833?email_source=notifications&email_token=AMG6MP5LJCPKLF5RNZLKS5DQQC4MRA5CNFSM4HHDAF72YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOECC4GFQ#issuecomment-545637142, or unsubscribe https://github.com/notifications/unsubscribe-auth/AMG6MP7C36A4GJEU5VJZD53QQC4MRANCNFSM4HHDAF7Q.
@jamuhl can be closed?
https://react.i18next.com/latest/trans-component#alternative-usage-v-11-6-0
I tried to use this but it doesn't work?
See https://codesandbox.io/s/react-i18next-forked-7kmz7?file=/src/i18n.js
Try not to use any void elements as keys
https://www.w3.org/TR/2011/WD-html-markup-20110405/syntax.html#syntax-elements
do not use void-elements as object key because html-parse-stringify2 will parse them as empty
@iamandrewluca indeed! thanks for quick help
Very nice that I came across this. Thank you very much for building this @iamandrewluca. My translations using Trans are way more clear now for translators! This should be the advised default instead of an alternative usage.
Most helpful comment
@klis87 duplication can be avoided.