【问题标题】:HTML tags in i18next translationi18next 翻译中的 HTML 标签
【发布时间】:2013-04-08 22:35:44
【问题描述】:

我正在使用i18next 为我的博客支持 i18n。它适用于纯文本内容,但是当我尝试翻译包含 HTML 标记的内容时,它会在我翻译文本时显示原始标记。

作为一个例子,下面是一个没有按预期工作的帖子的标记的 sn-p:

<div class="i18n" data-i18n="content.body">
  In Medellín they have many different types of <i>jugos naturales</i>&nbsp;(fruit juice) ... <br />
  <br />
  ...
</div>

翻译代码如下:

var resources = {
  "en": ...,
  "es": {
    "translation": {
      "content": {
        "body": "En Medellín hay varios tipos diferentes de <i>jugos naturales</i> ... <br /><br /> ... "
      }
    }
  }
}

i18n.init({"resStore": resources}, function( t ) {
  $('.i18n').i18n();
});

当翻译被渲染时,HTML标签被转义并输出为文本:

En Medellín hay varios tipos diferentes de &lt;i&gt;jugos naturales&lt;/i&gt;...&lt;br /&gt;&lt;br /&gt;

如何让 i18next 更改已翻译元素的 HTML?

【问题讨论】:

    标签: javascript internationalization i18next


    【解决方案1】:

    为了完成这项工作,您必须在要翻译的元素的 data-i18n 属性前面加上 [html]

    <div class="i18n" data-i18n="[html]content.body">
    

    来源:i18next.jquery.js

    【讨论】:

    • @user212218 我试过这个,但它不适合我。我正在使用纯 HTML 文件并使用 javascript 中的 i18n.load 函数加载翻译 JSON 文件。我正在尝试在页面的一个标题中使用 HTML 标记。 JSON:"abc" : "hi &lt;h2 class=\"header-class\"&gt;I am trying&lt;\/h2&gt; to use" html:&lt;span data-i18n="[html]abc" class="span-class"&gt;&lt;/span&gt; 我错过了什么?以上在浏览器中显示[html]abc
    • 正确解决方案!我确实不得不玩一点。这个例子可能有帮助:(1)在 js 代码中:_error_date_invalid 和(2)在 i18n json 中:“_error_date_invalid”:“这个日期不是有效
      请确保日期在明天到一年后"
    • 这里有一个更新的 jquery-i18next 指南:dev.to/adrai/…
    【解决方案2】:

    你需要关闭转义:

    i18n.t("key", { 'interpolation': {'escapeValue': false} })

    【讨论】:

    • 对于任何尝试在 React 中使用 react-i18-next 执行此操作的人,请注意 React 也会转义字符串!要告诉 React 不要转义字符串,我们必须使用 React 丑陋的 dangerouslySetInnerHTML 技术:&lt;div dangerouslySetInnerHTML={{__html: t('foo')}} /&gt;
    【解决方案3】:

    对于任何试图在 React 中执行此操作的人(例如使用 react-i18-next),请注意 React 会转义字符串!所以我们必须告诉 both i18n 和 React 不要转义字符串。

    • 为了告诉 i18n 跳过转义,我们使用 {escapeValue: false},正如其他人所展示的那样。

    • 为了告诉 React 跳过转义,我们使用 React 的 dangerouslySetInnerHTML 属性。

    <div dangerouslySetInnerHTML={
        {__html: t('foo', {interpolation: {escapeValue: false}})}
    } />
    

    该属性接受具有一个属性__html 的对象。 React 故意让它变得丑陋,以阻止它的使用,因为不转义可能很危险。

    为了安全起见,不应在此元素内使用原始用户输入。如果您确实需要在此处使用不受信任的字符串,请务必对其进行清理或转义,以便用户无法将原始 &lt;&gt; 注入页面。

    【讨论】:

    • 在使用任何用户输入时要小心,因为可能存在 XSS 攻击。我只是想在翻译中使用 HTML 标签,因此我选择了&lt;div dangerouslySetInnerHTML={ {__html: t('foo', {interpolation: {escapeValue: true}})} } /&gt;
    【解决方案4】:

    不要在翻译中加入 HTML 标签。无论如何,这是一个坏主意。 关注点分离 伙计们都会对此发牢骚。

    如果 react-i18next [https://react.i18next.com/latest/trans-component][1]

    ,请使用 &lt;Trans&gt; 组件

    这样做:

    // 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>",
    }
    

    这些数字 会让你觉得是随机的,但请耐心等待:

    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
    ]
    

    更多信息在这里:https://stackoverflow.com/a/62563302/537648

    【讨论】:

    • 我在这里缺少什么?似乎使用此解决方案,您现在无法在 Component.js 中使用硬编码的英文翻译。
    • 是的。英语为基础语言。这有点hacky,但在我们的例子中可以节省时间。
    【解决方案5】:

    i18n.t('key',{dateStr: date, interpolation: {escapeValue: false}})

    如果date='15/10/2020' 对我有用,也保留斜线

    【讨论】:

    • 但是html仍然被转义,我想知道你是否为html做了其他设置不被转义?
    【解决方案6】:

    来自documentation

    提示 3:转义:

    // given resources
    {           
      'en-US': { 
        translation: { 
          key1: Not escaped __nameHTML__,
          key2: Escaped __name__ 
        } 
      }
    };
    
    i18n.t("key2", { name: '', escapeInterpolation: true }); // -> Escaped &lt;tag&gt;
    i18n.t("key1", { name: '', escapeInterpolation: false }); // -> Not escaped <tag>
    

    为您的值添加后缀“HTML__”将防止转义,即使 选项是这样设置的。

    您可以在 init i18n.init({escapeInterpolation: true}); 上打开转义,或者像示例中那样将选项传递给 t 函数。

    【讨论】:

      【解决方案7】:

      您可以在全局初始化期间关闭转义:

      i18n.init({
        // ...
        interpolation: {
          escapeValue: false,
        }
      });
      

      【讨论】:

      • 请注意,如果您在应用程序的某处呈现用户输入,这可能会导致引入意外的安全问题(即 XSS)。
      • @FanaticD 仅当您使用 innerHTML = ... 这无论如何都不安全
      【解决方案8】:

      我同时使用 React 和 React Native。对于 React 应用程序该解决方案有效。不适用于 React Native。

      反应
      i18n.js

      interpolation: {
            escapeValue: false   
          }
      

      somefile.jsx

      <div dangerouslySetInnerHTML={{__html: t('dropZone.description')}} />
      

      反应原生
      此解决方案不起作用,因为在 Text 标记中不允许使用

      。我试图将 dangerouslySetInnerHTML 添加到 Text 标记中,但是什么都看不到。

      有人有 React Native 的解决方案吗?

      【讨论】:

      • 对于 React Native 你可以使用 String.fromCharCode 方法: const nonBreakingString = My Custom String${String.fromCharCode(160)}5
      【解决方案9】:

      ReactJS 中的解决方案:

      初始组件:

      ...
      <Typography>Hello <b>World</b><br />This is an <strong>example</strong></Typography>
      ...
      

      Interweavereact-i18next 一起使用

      ...
      import { Markup } from "interweave"
      ...
      <Typography><Markup content={t("paragraph")} /></Typography>
      ...
      

      还有你的 en.json 文件:

      {
       "paragraph": "Hello <b>World</b><br />This is an <strong>example</strong>"
      }
      

      es.json:

      {
       "paragraph": "Hola <b>Mundo</b><br />Esto es un <strong>ejemplo</strong>"
      }
      

      更多信息:Here

      【讨论】:

        猜你喜欢
        • 2017-02-11
        • 1970-01-01
        • 2019-07-16
        • 1970-01-01
        • 2015-11-11
        • 1970-01-01
        • 1970-01-01
        • 2012-10-27
        相关资源
        最近更新 更多