React中i18next翻译文件中的HTML标签

34

我在一个项目中使用i18next,并且无法避免将HTML标签包含在翻译文件中并使其正确呈现。

以下是我的.json翻译文件示例:

"en": {
  "product": {
    "header": "Welcome, <strong>User!</strong>"
  }
}

这个问题有一个很好的答案,但是与JQuery相关。我的项目不使用JQuery,而是React,并且这是我拥有的设置:

import i18next from 'i18next';
import en from 'locales/en';

i18next.
  init({
    lng: 'en',
    fallbackLng: false,
    resources: en,
    debug: false,

    interpolation: {
      escapeValue: false
    }
  });

export default i18next.t.bind(i18next);

在组件中,我有:

import t from 'i18n';

t('product.header')

我需要的HTML代码:

Welcome, <strong>User!</strong>

我收到的Html代码:

Welcome, &lt;strong&gt;User!&lt;/strong&gt

谢谢


1
你解决了这个问题吗? - Vittal Pai
@Petr Gaxarov - 如果您找到了解决方案,请分享。 - Sajith
我也遇到了同样的问题@Petr Gaxarov,你找到解决方案了吗? - Dhaval Parmar
5个回答

16
不要在翻译中放置HTML标签,这是个坏主意。关注点分离的人会对此大惊小怪。
如果使用react-i18nexthttps://react.i18next.com/latest/trans-component,请使用<Trans>组件。
操作步骤如下:
// Component.js

<Trans>Welcome, <strong>User!</strong>, here's your <strong>broom</strong></Trans>

以及相应的翻译文件:

// your locales/starwars_en.js file

translations: {
  "Welcome, <1>User!</1>, here's your <3>broom</3>": "Welcome, <1>young padawan!</1>, here's your <3>light saber</3>",
}

这些数字 <1><3> 看起来可能很随机,但请稍等:
Trans.children = [
  'Welcome, ',                        // index 0
  '<strong>User!</strong>'            // index 1
  ', please don't be ',               // index 2
  '<strong>weak</strong>',            // index 3
  ' unread messages. ',               // index 4
]

附注(可以考虑作为一种技巧,但可以节省大量时间):React.i18next.com的这些人在他们的文档中没有提到,但是你可以将基础语言(在这种情况下是英语)用作。这样可以节省时间,不需要像他们在文档中展示的那样进行双重翻译,我引用如下:

// Component file

import React from 'react';
import { Trans } from 'react-i18next'

function MyComponent({ person, messages }) {
  const { name } = person;
  const count = messages.length;

  return (
    <Trans i18nKey="userMessagesUnread" count={count}>
      Hello <strong title={t('nameTitle')}>{{name}}</strong>, you have {{count}} unread message. <Link to="/msgs">Go to messages</Link>.
    </Trans>
  );
}

// translation file

"userMessagesUnread": "Hello <1>{{name}}</1>, you have {{count}} unread message. <5>Go to message</5>.",
"userMessagesUnread_plural": "Hello <1>{{name}}</1>, you have {{count}} unread messages.  <5>Go to messages</5>.",


无论如何,“Kudos!”给i18next团队!你们太棒了,伙计们!
在这里 - go nuts

这个库毫无意义。阅读上面的翻译文件示例对于概念上如何工作毫无意义。它超出了基本示例的极其神秘的范畴,而且文档似乎并没有解释清楚。 - The Muffin Man

14
自从react-i18next@11.6.0版本以来,您可以在翻译字符串中使用标签,并将其替换为Trans组件的components属性或useTranslation hook的t属性: https://react.i18next.com/latest/trans-component#using-with-react-components 用法示例:
<Trans
  i18nKey="myKey" // optional -> fallbacks to defaults if not provided
  defaults="hello <italic>beautiful</italic> <bold>{{what}}</bold>" // optional defaultValue
  values={{ what: 'world'}}
  components={{ italic: <i />, bold: <strong /> }}
/>

是的,那是个好的解决方案,但如果我们的 JSON 文件本身有这种字符串 Welcome, &lt;strong&gt;User!&lt;/strong&gt,那么它将在用户界面上显示为 Welcome, &lt;strong&gt;User!&lt;/strong&gt - Dhaval Parmar
那么,有没有办法将 < 转换为 <,将 > 转换为 > 呢? - Dhaval Parmar
@DhavalParmar 相关答案:https://dev59.com/Nm025IYBdhLWcg3wyZIn - Jan Turoň

6

这不是react-i18next的问题 - 你不能将HTML添加到React元素中。React会保护你免受XSS漏洞的影响并转义内容:

更多详细信息和可能的解决方案:https://facebook.github.io/react/tips/dangerously-set-inner-html.html

但是请注意,如果您在此处放置未转义的用户内容,则会使您的站点遭受XSS攻击。

更安全的阅读React-i18next自述文件:https://github.com/i18next/react-i18next#interpolate-component

这使您可以拆分内容。

因此,“最佳”解决方案 - 至少我们所做的 - 是在翻译中使用Markdown,并使用例如:https://github.com/acdlite/react-remarkable将其转换为格式化内容。


从v4.4.0开始,我们增加了一个新组件,使得将React组件包含到翻译中变得简单。 https://react.i18next.com/components/trans-component.html - jamuhl
你发布的链接已经失效。 - gsouf
1
我喜欢使用react-remarkable的建议,并在GitHub上分享了i18n-react-app,以展示如何修改“Create React App”样板文件以结合i18next和Markdown。我选择了react-markdown,因为react-remarkable似乎不再维护。 - Mogsdad
1
@jamuhl 这个链接是 https://react.i18next.com/latest/trans-component - Andreas Norman

1
你可以尝试使用属性dangerouslySetInnerHTML。这使您可以在JSON中使用HTML,该HTML将呈现在标记中。
请注意,您不能同时拥有此属性和子元素。
使用示例:
<p dangerouslySetInnerHTML={{__html: t(`users_desc`) }} />

在 JSON 中你可以像这样写
{
...
"users_desc": "Users  are <b> Amazing </b>"
...
}

这将呈现一个带有标签作为子元素的标记


-3

首先,您需要像这样编写您的JSON文件:

"en":{
   "Welcome":"Welcome",
   "User":"User"
}

然后按如下方式编写您的HTML代码:

<header>{t('Welcome')},<strong>{t('User')}!<strong>
<header>

<header>t('欢迎')</header><strong>{t('用户')}!</strong><header> - mahdieh mahmoodi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接