如何在expressJS中保持语言状态的变化

时间:2018-10-11 06:30:25

标签: javascript node.js express internationalization

我正在使用nodeJ,handlebars和expressJs框架进行项目。我使用i18n-express模块添加了更改语言功能。当我们要更改语言时,此模块在url的末尾添加查询字符串。现在的问题是,当我将一页移到另一页时,查询字符串将被删除并丢失其state.so如何维护语言状态?如果用户选择法语,则所有页面均以法语打开。这就是我要的。

代码:

var i18n =  require("i18n-express");

app.use(i18n({
  translationsPath: path.join(__dirname, 'lang'), // <--- use here. Specify translations files path.
  siteLangs: ["ar","en","cn","fr","ge","he","hu","it","ja","ko","es","ru"],
  cookieLangName : 'ulang',
  textsVarName: 'translation'  
}));

链接以更改语言

<a href="#!" id="{{icon}}" onclick=" return changeLanguage(this)"></a>

Onclick功能更改语言

function changeLanguage(event){
   $('#languages img').attr('src','/images/flag-icons/'+event.id+'.png');
   var url = window.location.href;
   url = url.split("?")[0];
   url += '?clang='+event.id;
   window.location.href = url;
   localStorage.setItem("clang", '?clang='+event.id); //event.id returns locale name such as en, ar, sp, fr etc.
   //console.log(url);
}

4 个答案:

答案 0 :(得分:1)

在客户端,如果您能够在本地存储上设置一个项目,那么您也可以获取相同的项目并将其值也推入查询字符串。因此,您基本上需要在客户端javascript上具有一个附加功能,该功能将在每次打开页面时获取该项目。

    function getParameterByName(name, url) {
        if (!url) url = window.location.href;
        name = name.replace(/[\[\]]/g, '\\$&');
        var regex = new RegExp('[?&]' + name + '(=([^&#]*)|&|#|$)'),
            results = regex.exec(url);
        if (!results) return null;
        if (!results[2]) return '';
        return decodeURIComponent(results[2].replace(/\+/g, ' '));
    }

    function checkLanguageFromLocalStorage(){
        var clang = getParameterByName('clang');
        if (clang == null) {
            if (localStorage.getItem("clang") != null) {
                var clang = localStorage.getItem("clang");
                var url = window.location.href;
                url = url.split("?")[0];
                url += '?clang='+clang;
                window.location.href = url;
            }
        }
    }

    checkLanguageFromLocalStorage();

答案 1 :(得分:1)

我推荐您Lingua for ExpressJS

基本上,Lingua是Express.js的中间件,可帮助您轻松地使Web应用程序国际化。它确定用户代理的语言,并将i18n资源推送到您的视图。

$ npm install -s lingua

var express = require('express'),
    lingua  = require('lingua');

// Express app configuration code and lingua init.
app.configure(function() {

app.set('views', __dirname + '/views');
app.set('view engine', 'ejs');

// Lingua configuration
app.use(lingua(app, {
    defaultLocale: 'en',
    path: __dirname + '/i18n'
}));

app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(express.static(__dirname + '/public'));
app.use(app.router);

语言文件

'./i18n/en.json' and './i18n/de-de.json').

// en.json
    {
        "title": "Hello World",
        "content": {
            "description": "A little description."
        }
    }

// de-de.json
    {
        "title": "Hallo Welt",
        "content": {
            "description": "Eine kleine Beschreibung."
        }
    }

您可以轻松地在页面上实现它:

<h1><%= lingua.title %></h1> <!-- out: <h1>Hello World</h1> -->
<p><%= lingua.content.description %></h1> <!-- out: <p>A little description.</p> -->

答案 2 :(得分:1)

为什么不使用语言而不是查询参数传递cookie? i18n-express有一个名为cookieLangName的{​​{3}},您已经在服务器端(cookieLangName: 'ulang')上进行了配置。设置cookieLangName可使i18n-express从cookie中读取具有您传递的名称的语言。您所需要做的就是在客户端脚本中的changeLanguage函数内部设置此cookie,它将完成此操作:

function changeLanguage(event){
   $('#languages img').attr('src','/images/flag-icons/'+event.id+'.png');
   document.cookie = `ulang=${event.id}; path=/`;

   localStorage.setItem("ulang", `ulang=${event.id}; path=/`); // you can still save it to localStorage and synchronize it when cookie is removed
}

答案 3 :(得分:1)

我认为要求可以归结为:

如果最终用户选择了一种语言,则该选择在URL中应始终是透明的,以便启用翻译模块的正常功能。满足此要求不应导致不必要的页面重新加载。但是,此问题的范围忽略了以下事实:在不存在clang=xx的冷启动情况下,由于以前的用户选择仅是客户端已知的,因此需要手动重定向才能加载正确的内容。< / em>

根据您发布的摘录,您快到了。函数changeLanguage以所选语言正确加载内容。但是,如果我正在对其进行代码审查,则将要求对以下结果进行一些更改:

修补的HTML

<a href="#!" id="{{icon}}" onclick="return loadContentInSelectedLanguage(this.id)"></a>

修补的JS:

function processLanguageSelection(selectedLang) {

  highlightCurrentlySelectedLang(selectedLang);
  saveSelectedLangAcrossSession("clang", selectedLang);

  reloadContentInSelectedLang(selectedLang);
}

function highlightCurrentlySelectedLanguage(selectedLang) {
  $('#languages img').attr('src', '/images/flag-icons/' + selectedLang + '.png');
}

function saveSelectedLangAcrossSession(entryKey, selectedLang) {
  window.localStorage.setItem(entryKey, selectedLang);
}

function reloadContentInSelectedLang(selectedLang) {
  var search = window.location.search || "?";

  if (/clang=\w{2}/.test(search)) {
    search = search.replace(/clang=\w{2}/, "clang=" + selectedLang);
  } else {
    search += ("?" === search ? "clang=" : "&clang=") + selectedLang;
  }

  window.history.replaceState(null, "", search);
  window.location.reload();
}

您快要在那里了,就像我说的那样。 所以,剩下的才是最终的?- 缺少的芯片是:刚开始加载页面时,应应用先前的用户选择。并且所有必要的重定向都应在浏览器开始处理文档正文之前尽早完成。 当然,这意味着您的脚本中担负此责任的部分应该是在内部运行的第一件事<head>...</head>部分。

<head>
  <script>
    (function() {
      var previouslySelectedLanguage = window.localStorage.getItem("clang");

      if (/clang=\w{2}/.test(window.location.search)) {
        // correct content should have been loaded in this case
        // otherwise the server needs fixing, but that's not
        // in the scope of this question.

        // determine selectedLang from window.location.search, then..
        highlightCurrentlySelectedLanguage(selectedLang);

        if (!previouslySelectedLanguage || "selectedLang" !== previouslySelectedLanguage) {
          saveSelectedLangAcrossSession("clang", selectedLang);
        }

        return;
      }

      if (previouslySelectedLanguage) {
        // redirect
        reloadContentInSelectedLang(previouslySelectedLanguage);
      }
    })();

  </script>
</head>

请注意,此答案中提供的示例尚未投入生产。通过确保它们的健壮性,弹性和满足组织中要求的其他标准来进行尽职调查。例如,此正则表达式/clang=\w{2}/做出了一个大胆的假设,不一定总是正确的。