【问题标题】:Javascript translation script improvementJavascript翻译脚本改进
【发布时间】:2018-04-28 08:22:10
【问题描述】:

我已经阅读了几篇关于这个主题的文章和一些像this one 这样的 SO 问题,但没有什么真正适合我的情况。

所以基本上我正在创建简单的单页应用程序,几乎不涉及任何 javascript。我唯一需要 JS 的地方就是这个翻译。一般来说,在 JS 中创建一些脚本来翻译对我来说不是问题,所以我这样做了:

我正在将两个文件导入我的 index.html:

<script src="js/text.js"></script>
<script src="js/translator.js"></script>

text.js 我有一个常量对象,其中包含网站要显示的文本:

// Global constant "text" accessible in translator.js file
const text = {
    PL: {
        aboutHeading: "Kilka słów o mnie"
    },
    ENG: {
        aboutHeading: "Few words about me"
    }
};

translator.js 我有一个对象负责检查哪种语言并填充 div/标题/任何文本:

// global translator object
const translator = {
    currentLanguage: '',
    checkLanguage() {
        switch (window.navigator.language) {
            case 'pl':
            case 'pl-PL': {
                this.currentLanguage = 'pl';
                break;
            }
            case 'en': {
                this.currentLanguage = 'eng';
                break;
            }
            default: {
                this.currentLanguage = 'eng';
                break;
            }
        }
        //alert(this.currentLanguage);
        //alert(window.navigator.language);
    },
    fillText(lang) {
        if(lang === 'pl') {
            document.getElementById('few-words-about-me-header').innerHTML = text.PL.aboutHeading;
            alert('inserted pl');
        }
        if(lang === 'eng') {
            document.getElementById('few-words-about-me-header').innerHTML = text.ENG.aboutHeading;
            alert('inserted eng');
        }
    },
};

translator.checkLanguage();
translator.fillText(translator.currentLanguage);

document.getElementById('polish-flag').addEventListener('click', () => {
    translator.fillText('pl');
});
document.getElementById('english-flag').addEventListener('click', () => {
    translator.fillText('eng');
});

通常一切都按预期工作,我唯一担心的是我这里有两个全局变量,我不确定该怎么做。我觉得我可以用更高效、更漂亮的方式来完成这个翻译。

所以问题是 - 拥有这两个全局变量是否可以,我是否可以以更漂亮的方式实现与上述代码相同的效果?

【问题讨论】:

  • 好吧,如果您要使用某种翻译脚本,那么您将不可避免地使用全局变量。减少你拥有的数量是很好的,但它们为零也并不总是可行的。话虽如此,如果您使脚本在页面加载时仅运行一次,则可以避免这种情况。不过,我可能不会担心。你最好去图书馆寻找像i18next这样的翻译,这样你就不必重新发明轮子了。

标签: javascript translation


【解决方案1】:

只需将两者都封装在一个脚本中的 IIFE 中,这样就不会污染全局命名空间。

// main.js
(() => {
  const text = {
    PL: {
      aboutHeading: "Kilka słów o mnie"
    },
    ENG: {
      aboutHeading: "Few words about me"
    }
  };
  const translator = {
    currentLanguage: '',
    checkLanguage() {
      switch (window.navigator.language) {
        case 'pl':
        case 'pl-PL':
          {
            this.currentLanguage = 'p';
            break;
          }
        case 'en':
          {
            this.currentLanguage = 'eng';
            break;
          }
        default:
          {
            this.currentLanguage = 'eng';
            break;
          }
      }
      //alert(this.currentLanguage);
      //alert(window.navigator.language);
    },
    fillText(lang) {
      if (lang === 'pl') {
        document.getElementById('few-words-about-me-header').innerHTML = text.PL.aboutHeading;
        alert('inserted pl');
      }
      if (lang === 'eng') {
        document.getElementById('few-words-about-me-header').innerHTML = text.ENG.aboutHeading;
        alert('inserted eng');
      }
    },
  };

  translator.checkLanguage();
  translator.fillText(translator.currentLanguage);

  document.getElementById('polish-flag').addEventListener('click', () => {
    translator.fillText('pl');
  });
  document.getElementById('english-flag').addEventListener('click', () => {
    translator.fillText('eng');
  });
})();

如果您出于某种原因必须动态创建text,则可以改用&lt;script type="application/json"&gt; 来避免在那里创建全局变量,它是可解析的,但不会自动添加到全局命名空间中。例如:

<div></div>
<script type="application/json">{"foo": "foo", "bar": "bar"}</script>
<script>
(() => {
  const text = JSON.parse(document.querySelector('script[type="application/json"]').textContent);
  document.querySelector('div').textContent = text.foo + ' / ' + text.bar;
})();
</script>

您还可以使用对象查找来简化currentLanguage 设置。与替代方案相比,switch 语句通常过于冗长且容易出错:

checkLanguage() {
  const languages = {
    pl: ['pl', 'pl-PL'],
    en: ['eng'],
  };
  const navigatorLanguage = window.navigator.language;
  const foundLanguageObj = Object.entries(languages)
    .find(([setting, arr]) => arr.includes(navigatorLanguage));
  this.currentLanguage = foundLanguageObj ? foundLanguageObj[0] : 'eng';
}

【讨论】:

  • 我可以在&lt;script type="application/json"&gt; 中有对象,就像这个有问题的 text.js 吗?我通常喜欢将 translate.js 放入 IIFE 的想法,但我想将 text.js 文件与 translate.js 文件分开
  • 在我的示例中,application/json 中的内容 对象 - 您可以将其替换为您想要的任何内容。 (它也可以是一个数组,或者一个基元)
  • 我的意思是我在 index.html 中导入 text.js 时将类型更改为 application/json,现在我正试图从 translate.js 控制台记录这个对象,如下所示:console.log(document.querySelector('script[type="application/json"]').textContent); 但它正在安慰空字符串,我尝试了.value 而不是 textContent 没有运气。
  • 因为它是空字符串我不能 JSON.parse 它
  • 要使用application/json,您必须像我在sn-p 中所做的那样将其填充在页面本身 中,而不是在外部文件中。如果您无法更改页面,另一种选择是发出网络请求,例如fetch('js/text.js').then(res =&gt; res.json()).then(text =&gt; { /* do stuff with text */ })
猜你喜欢
  • 2012-03-13
  • 2010-09-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-01
  • 2018-02-05
  • 2015-04-09
相关资源
最近更新 更多