VUE-I18N翻译中HTML标签的最佳实践



我正在使用vue-i18n,我需要在中间翻译带有锚标签的句子。显然,我想将HTML特定的标记放在我的翻译中,但是如何最好地处理?

考虑以下示例:

This is a test sentence which cannot 
<a href="https://example.com" class="test-class test-another-class">be split</a> 
or it will not make sense

我唯一可以提出的解决方案是:

{
    "en": {
        "example": "This is a test sentence which cannot {linkOpen}be split{linkClose} or it will not make sense"
    }
}

,然后在组件模板中

<p v-html="$t('example', { 
    'linkOpen': `<a href="https://example/com" class="test-class test-another-class">`,
    'linkClose: '</a>'
    }) 
"></p>

不完全优雅...

编辑:我已经对此进行了测试,并且实际上没有工作(不能将HTML放入参数中),所以现在我真的没有想法了!

您可以为链接提出一些简单的标记并编写一个小的转换功能,例如:

//In this example links are structured as follows [[url | text]]
var text = `This is a test sentence which 
cannot [[https://example.com | be split]] or it will not make sense`
var linkExpr = /[[(.*?)]]/gi;
var linkValueExpr = /(s+|s+)/;
var transformLinks = (string) => {
  return text.replace(linkExpr, (expr, value) => {
    var parts = value.split(linkValueExpr);
    var link = `<a href="${parts[0]}">${parts[2]}</a>`;
    return link;
  });
}
alert(transformLinks(text));

jsfiddle:https://jsfiddle.net/ru5smdy3/

使用vue-i18n,它看起来像这样(当然可以简化哪个):

<p v-html="transformLinks($t('example'))"></p>

您可以将HTML放入不属于显示DOM的一部分的元素中,然后提取其textContent。不过,这可能对您实际尝试做的事情不起作用。我不能说。

new Vue({
  el: '#app',
  data: {
    html: `This is a test sentence which cannot 
<a href="https://example.com" class="test-class test-another-class">be split</a> 
or it will not make sense`,
    utilityEl: document.createElement('div')
  },
  methods: {
    htmlToText: function (html) {
      this.utilityEl.innerHTML = html;
      return this.utilityEl.textContent;
    }
  }
});
<script src="//cdnjs.cloudflare.com/ajax/libs/vue/2.2.1/vue.js"></script>
<div id="app">
  <p v-html="html"></p>
  <p>{{htmlToText(html)}}</p>
</div>

我发现自己处于类似情况,我建议使用vue-i18n插槽。

我有一个JSON I18N文件,该文件具有HTML的错误消息。这些渲染良好,但不会以Vue模板的形式编译,并且无法具有绑定。当用户单击给定错误消息中的链接时,我想调用onclick函数。

在我的示例中,我有一个带有一些状态消息的蛋糕状态JSON:

// cake_state.json, where I want links in error messages to call a function when clicked
{
  "state":{
        "stage": {
            "mixing": "Cake is being mixed. The current time is {time}",
            "resting": "Cake is resting. The current time is {time}",
            "oven": "Cake is cooking. The current time is {time}"
            },
        "error": {
            "ovenIssue": "Oven of brand is malfunctioning. Click {email_support_link} to get help",
            "chefIssue": "Chef is down. Click {email_support_link} to get help",
            "leakIssue": "There is a leak"
            },
  }
}
                  

现在,如果我们有一些VUE SFC,则具有模板:

<template>
   <div>
     <i18n :path="getMessage">
        <!-- enter various i18n slots -->
        <template #time>
          <span>{{ getTime }}</span>
        </template>
        
        <template #email_support_link>
          <!-- binding now works because it is not v-html -->
          <a href="" @click.prevent="getRightSupportDepartment">here</span>
        </template>
       </i18n>
    </div>
</template>
...
// js
computed: {
    getTime(): string { //implementation ...},
    getRightSupportDepartment(): string { //implementation ...},
    
    //return strings that are keys to cake_state.json messages
    getMessage(): string {
        ...
        switch (this.cakeState) {
          case Failure.Overheat:
            return "state.error.ovenIssue";
          case Failure.ChefIdle:
            return "state.error.chefIssue";
          case Failure.LeakSensor:
            return "state.error.leakIssue";

所以我们在这里看到的是:

  1. getMessage功能为我们提供了I18N JSON中消息的关键。这将传递到i18n组件
  2. i18n组件范围中的<template #XXX>插槽从该函数中提供了此键,该键获取相应的消息,然后
  3. 如果相关消息具有任何关键字,则将其从相应的模板中放入。

要重新征服,它有助于提供一种与HTML元素具有vue绑定的方法

例如,现在我们可能会看到"品牌的烤箱都出现故障。单击此处获取帮助&quot",当用户单击"此处"时,我们可以运行一个单击功能。

最新更新