使用expressjs和jade的动态(i18n)链接



我正在使用expressjs和i18n节点(https://github.com/mashpie/i18n-node)。它正在工作,除了优雅的链接。我现在拥有的是:

app.all(/^/(w{2}/)+(w*)?/, function(req, res, next) {
    var lang = req.params[0];
    var type = req.params[1];
    req.url = req.url.replace(lang, "");
    if(type !== 'javascript' && type !== 'img' && type !== 'css') {
      i18n.setLocale(lang.slice(0, 2));
    }   
    next();
});

(我希望/foo和/en/foo都能工作)。如果url中未指定语言,则会检查标头,如果未指定,则默认为英语。顺便说一句,我的解决方案似乎不太理想(我必须手动检查它是否不是静态内容),所以如果你们中有人有更好的解决方案,我会洗耳恭听。

现在,我真正的问题是建立内部内容的链接。如果用户在这里:"/en/foo","/bar"链接实际上应该是"/en/bar"。我正在使用翡翠(除了它是默认的之外,没有其他特别的原因,再次接受建议。)

我试着给Jade添加一个助手功能:

app.helpers({
  __i: i18n.__
  ,__n: i18n.__n
  ,link_to: function(link, text) {
    //TODO: how to get request here?
    // this should be defined to the absolute base path
    var baseUrl = "/";
    // only append locale if it is part of the existing url!
    var locale = i18n.getLocale();
    return '<a href="' + baseUrl + locale + '/' + link + '">' + text + '</a>';
  }
});

但它有很多问题:

  1. 如何获取基本url?例如,如果网站位于http://www.example.com/foo/bar,并且我链接到"testLink",link_to将生成http://www.example.com/foo/bar/testLink",而不是"/testLink"或"http://www.example.com/testLink"等
  2. 如何确定url是否包含本地化参数?如果没有必要的话,我不想在链接中添加本地化参数
  3. 功能本身并不伟大;在Jade中,它被称为::=link_to("testUrl","一些链接描述")。我宁愿这样做:link_to(href="someUrl")div更多的翡翠代码
  4. (minor)HTML是直接在JS中编写的

做这件事的首选方式是什么?我一直在找,但找不到一个好的答案。。

这实际上也是一个普遍的问题;即如何链接到其他内部内容,如Rails中的link_to。仅仅做一个(href="someAction")是不够的,因为你希望它生成绝对的URL,这样漂亮的URL就不会破坏静态内容链接。

谢谢!

我用i18n粘贴自己项目的代码,我用一个类作为dicto,用另一个类通过IP:搜索语言

app.configure(function(){
  app.set('views', __dirname + '/views');
  app.set('view engine', 'jade');
  app.use(express.bodyParser());
  app.use(express.methodOverride());
  app.use(express.cookieParser());
  app.use(express.session({
        secret: "sessid",
        key: 'uwsid',
        store: sessionStore
  }));
  app.use(function (req,res,next) {
      if (req.session.uid) {
          req.lang = req.session.uid.lang;
          next();
      } else if (req.cookies.lang) {
          req.lang = req.cookies.lang;
          next();
      } else {
          var alang = typeof req.headers['accept-language'] != "undefined" ? req.headers['accept-language'].substr(0,2) : null;
          var ipinfows = ipinfo.getInstance();
          ipinfows.getInfo(req.connection.remoteAddress, function (err,data) {
              if (err) {
                  req.lang = alang;
                  res.cookie('lang', alang);
              } else if (data && data.error) {
                  req.lang = alang;
                  res.cookie('lang', alang);
              } else {
                  console.log("seteando");
                  req.lang = data.lang.toLowerCase();
                  for (i in countryLangs) {
                      if (countryLangs[i].indexOf(data.lang) != -1) {
                          req.lang = i;
                      }
                  }
                  if (alang != req.lang) {
                      req.langdifference = alang;
                  }
                  res.cookie('lang', req.lang);
              }
              next();
          });
      }

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

路由app.use(app.router)之前你可以定义回调,在这种情况下,我搜索lang并在cookie中定义它。在我添加dynamicHelper以将Dicto对象包含到模板中之后:

app.dynamicHelpers({
  i18n: function (req,res) {
      return new i18n({lang: req.lang});
  }
});

在路由之前定义lang。(保存在req.lang中),我现在可以使用模板中的i18n哈尔珀(带翡翠):

form.uniForm(action="/account",method="post")
    fieldset.inlineLabels
        .ctrlHolder
            label(for="nickname") #{**i18n.getText('user:nick')**}:
            input(type="text",name="nickname",value=everyauth.user.nick)
            p.formHint

i18n对象现在与动态助手上定义的对象相同。

据我所知,express只会调用一次helper函数(编译模板时…)

在快速指南中,http://expressjs.com/guide.html,查看dynamicHelpers,它应该对您的情况更有用(dynamicHelpers提供请求和响应对象)。

最新更新