Подтвердить что ты не робот

Многоязычные маршруты в express.js?

Мне интересно, есть ли пример лучшей практики, как реализовать многоуровневые маршруты в express.js. я хочу использовать заголовок accept-language, чтобы получить язык браузера, а затем автоматически перенаправить на соответствующий языковой маршрут, например

www.foo.bar/de/startseite ИЛИ www.foo.bar/en/home

Любые советы по этому поводу?

4b9b3361

Ответ 1

Я сделал следующее: установите модуль i18n- node и зарегистрируйтесь в выражении js. вот код.

var express = require('express')
  , routes = require('./routes')
  , http = require('http')
  , i18n = require("i18n");

  var app = express();

i18n.configure({
    // setup some locales - other locales default to en silently
    locales:['de', 'en'],
    // disable locale file updates
    updateFiles: false
});

app.configure(function(){
  ...
  app.use(i18n.init);
  ...
});
// register helpers for use in templates
app.locals({
  __i: i18n.__,
  __n: i18n.__n
});

после этого установите следующее, чтобы получить все запросы

// invoked before each action
app.all('*', function(req, res, next) {
    // set locale
    var rxLocal = /^\/(de|en)/i;
    if(rxLocal.test(req.url)){
        var arr = rxLocal.exec(req.url);
        var local=arr[1];
        i18n.setLocale(local);
    } else {
        i18n.setLocale('de');
    }
    // add extra logic
    next();
});

app.get(/\/(de|en)\/login/i, routes.login);

может быть, эта помощь.

Ответ 2

Я просто передам содержимое на обнаруженном языке напрямую.

Например, example.com/home обслуживает домашнюю страницу в наилучшем доступном Accept-Language (возможно, переопределяется файлом cookie, если вы предоставляете опцию выбора языка на самом сайте).

Вы хотите, чтобы ваш ответ Vary: заголовок включал Accept-Language.

IMO, включая коды языков в URI, является уродливым взломом. Цель RFC заключается в том, что единый ресурс (ваша домашняя страница) универсально представлен одним URI. Объект, возвращаемый для URI, может варьироваться в зависимости от другой информации, такой как языковые предпочтения.

Подумайте, что происходит, когда немецкоязычный пользователь копирует URL-адрес и отправляет его англоязычному пользователю. Этот получатель предпочел бы видеть ваш сайт на английском языке, но поскольку он получил ссылку, указывающую на example.com/de/startseite, он переходит прямо к немецкой версии.

Очевидно, что это не идеально подходит для полной интернационализации того, что пользователь видит в адресной строке (поскольку на дому находится английский язык), но это больше соответствует намерениям RFC, и я бы сказал, что он работает лучше для пользователей, особенно когда ссылки распространяются по электронной почте/социальной/независимо.

Ответ 3

Рекомендация промежуточного уровня

Ответ от @miro очень хорош, но может быть улучшен, как в следующем промежуточном программном обеспечении в отдельном файле (как предлагает @ebohlman).

Среднее ПО

module.exports = {
  configure: function(app, i18n, config) {
    app.locals.i18n = config;
    i18n.configure(config);
  },
  init: function(req, res, next) {
    var rxLocale = /^\/(\w\w)/i;
    if (rxLocale.test(req.url)){
      var locale = rxLocale.exec(req.url)[1];
      if (req.app.locals.i18n.locales.indexOf(locale) >= 0)
        req.setLocale(locale);
    }
    //else // no need to set the already default
    next();
  },
  url: function(app, url) {
    var locales = app.locals.i18n.locales;
    var urls = [];
    for (var i = 0; i < locales.length; i++)
      urls[i] = '/' + locales[i] + url;
    urls[i] = url;
    return urls;
  }
};

Также в примере проекта github.

Объяснение

Среднее ПО имеет три функции. Первый - это небольшой помощник, который настраивает i18n-node, а также сохраняет настройки в app.locals (не выяснили, как получить доступ к настройкам самого i18n-node).

Основной из них - второй, который берет язык из URL-адреса и устанавливает его в объект запроса.

Последний - это помощник, который для данного url возвращает массив со всеми возможными локалями. Например, называя его '/about', мы получим ['/en/about', ..., '/about'].

Как использовать

В app.js:

// include
var i18n = require('i18n');
var services = require('./services');

// configure
services.i18nUrls.configure(app, i18n, {
  locales: ['el', 'en'],
  defaultLocale: 'el'
});

// add middleware after static
app.use(services.i18nUrls.init);

// router
app.use(services.i18nUrls.url(app, '/'), routes);

ссылка Github

Доступ к языку можно получить, например, от любого контроллера с помощью i18n-node req.getLocale().

RFC

То, что @josh3736 рекомендует, безусловно совместимо с RFC и т.д. Тем не менее, это довольно распространенное требование для многих веб-сайтов и приложений i18n, и даже Google уважает те же ресурсы, локализованные и обслуживаемые под разными URL-адресами (это можно проверить в инструментах для веб-мастеров), Однако я бы рекомендовал иметь один и тот же псевдоним после lang-кода, например /en/home, /de/home и т.д.

Ответ 4

Не знаете, как вы планируете организовывать или обмениваться контентом, но вы можете использовать регулярные выражения с экспресс-маршрутами, а затем создавать разные шаблоны. Что-то вроде этого:

app.get(/^\/(startseite|home)$/, function(req, res){

});

Одна вещь, которую я сделал, - это организовать мой контент с субдоменами, а затем использовать промежуточное программное обеспечение, чтобы захватить контент из базы данных, основанной на разбиении URL-адреса, но все они используют одни и те же маршруты и шаблоны.

Ответ 5

Напишите функцию промежуточного программного обеспечения, которая анализирует любые заголовки "Accept-Language" и устанавливает локальную переменную уровня запроса на соответствующий код (например, двухбуквенный код языка) со значением по умолчанию (например, "en" ), если есть нет таких заголовков или вы не поддерживаете ни один из перечисленных языков. На ваших маршрутах загрузите локальный файл и привяжите его к любым именам файлов шаблонов и ответьте на него, если есть какая-либо зависящая от языка обработка, отличная от выбора шаблона.