Динамические (i18n) ссылки с использованием expressjs и jade - PullRequest
3 голосов
/ 05 февраля 2012

Я использую expressjs и i18n-node (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 (без особой причины, кроме того, что это было по умолчанию, снова открыт для предложений ..)

Я попытался добавить вспомогательную функцию в 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") еще немного нефритового кода
  4. (несовершеннолетний) HTML написан непосредственно в JS

Каков предпочтительный способ сделать это? Я искал и искал, но не смог найти хороший ответ ..

Это на самом деле также общий вопрос; Т.е. как вы ссылаетесь на другой внутренний контент, такой как link_to в Rails. Просто сделать (href = "someAction") недостаточно, поскольку вы хотите, чтобы он генерировал абсолютные URL-адреса, чтобы красивые URL-адреса не нарушали статические ссылки на контент.

Спасибо!

Ответы [ 2 ]

2 голосов
/ 25 июня 2012

Я вставляю код из собственного проекта с 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 (приложение.router); вы можете определить обратные вызовы, в этом случае я ищу lang и определяю его в cookie.После того как я добавлю dynamicHelper для включения объекта Dicto в шаблон:

app.dynamicHelpers({

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

});

С определением lang перед этой маршрутизацией.(сохранение в req.lang). Теперь я могу использовать вспомогательный инструмент i18n из шаблона (с jade):

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 определен в динамическом помощнике.

0 голосов
/ 25 июня 2012

Насколько я понимаю, express будет вызывать вспомогательную функцию только один раз (когда шаблон компилируется ...)

В экспресс-руководстве http://expressjs.com/guide.html, ознакомьтесь с dynamicHelpers, который должен быть более полезным для вашей ситуации (dynamicHelpers предоставляет объекты запроса и ответа).

...