Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature Proposal: Trans prop to wrap text nodes in a user-specified element #1323

Closed
feross opened this issue May 26, 2021 · 3 comments · Fixed by #1324
Closed

Feature Proposal: Trans prop to wrap text nodes in a user-specified element #1323

feross opened this issue May 26, 2021 · 3 comments · Fixed by #1324

Comments

@feross
Copy link
Contributor

feross commented May 26, 2021

🚀 Feature Proposal

A Trans prop to wrap text nodes in a user-specified element, i.e. <span>, or a top-level i18next instance option to do the same.

<Trans
  t={t}
  i18nKey='...'
  wrapTextNodes='span'
/>

Motivation

We would like a way to wrap each "text part" (i.e. HTML text node) of a translation in a <span> element so we can work around a well-known Google Translate issue with React apps. See: facebook/react#11538 When the user activate the built-in Google Translate functionality in Chrome, or uses a browser extension to do the same, then React throws an exception which breaks the entire app. We can't control when/if users trigger Google Translate functionality on our app, so we need a way to prevent React from crashing.

Right now, when using the <Trans> component with interpolation, any text outside of the "interpolation tag" is added to the DOM directly as a TextNode. It's not wrapped in a <span> or any other HTML element.

Here's an example. Take the <Trans> component used like this:

<div>
  <Trans
    t={t}
    i18nKey='myKey'
    components={{
      tooltip: <TooltipText label='This is a tooltip' />
    }}
  />
</div>

With the key myKey defined as follows:

We use <tooltip>end-to-end encryption</tooltip> and a link that automatically expires

The produced HTML looks like:

<div>
  Wormhole lets you share files with
  <span class="css-7fgewl">end-to-end encryption</span>
  and a link that automatically expires.
</div>

Note the two TextNodes (Wormhole lets you share files with and and a link that automatically expires.) which are not wrapped in a <span> or any kind of wrapper element.

This completely breaks Google Translate due to the bare text nodes. The well-known workaround is to wrap all TextNodes in a <span>.

Example

A Trans prop to wrap text nodes in a user-specified element, i.e. <span>, or a top-level i18next instance option to do the same.

<Trans
  t={t}
  i18nKey='...'
  wrapTextNodes='span'
/>

Other note

It appears that the v9 <Interpolate> component may have had an option similar to this (dangerouslySetInnerHTMLPartElement) which defaulted to wrapping text in <span> but it appears that it had a slightly different use case and didn't make it into <Trans>.

@jamuhl
Copy link
Member

jamuhl commented May 27, 2021

Guess we could patch this faster than google translate will be fixed ;)

Should be a rather easy change...

If you like feel free to help out with a pull request?

@feross
Copy link
Contributor Author

feross commented May 27, 2021

@jamuhl Sure thing. Here's a PR: #1324 I decided to just add a single top-level option, similar to how the existing trans* top-level options don't have prop equivalents. I think this addresses the Google Translate use case.

adrai added a commit that referenced this issue May 28, 2021
* Add `transWrapTextNodes` option

The `transWrapTextNodes` option instructs react-i18next to wrap text nodes in a user-specified element. By default, text nodes are not wrapped.

Fixes: #1323

* added test for #1324

Co-authored-by: Adriano Raiano <[email protected]>
@adrai
Copy link
Member

adrai commented May 28, 2021

released with v11.10.0

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants