html текст
All interests
  • All interests
  • Design
  • Food
  • Gadgets
  • Humor
  • News
  • Photo
  • Travel
  • Video
Click to see the next recommended page
Like it
Don't like
Add to Favorites

Настраиваем NGINX для мультиязычных сайтов tutorial


Уже давно считается хорошим тоном отдавать контент сайта на языке, предпочитаемом пользователем. Некоторые сервера определяют язык по месту нахождения пользователя с помощью модулей геолокации, остальные берут настройки браузера. Языковые предпочтения пользователя часто сохраняются в cookie, и затем используются при повторном визите.

Какой метод определения языка пользователя подходит лучше – вопрос достаточно спорный. Мой личный ранг значимости языковой информации (в порядке убывания): cookie, настройки браузера, регион.

Для поисковых систем, социальных сетей и прочих агрегаторов информации важно знать, на каком языке должна быть проиндексирована или загружена страница, например в качестве миниатюры в хронику фейсбука. Это значит, что ссылка должна однозначно указывать на язык.

Распространенные варианты кодирования языковой информации о ресурсе следующие:
  • каждая языковая версия на отдельном субдомене, например en.example.com, ru.example.com
  • язык ресурса указывается в префиксе URI, например example.com/en/, example.com/ru
  • язык ресурса указывается в GET параметре, например example.com?lang=en, example.com?lang=ru

Первый вариант наиболее радикальный, каждая языковая версия сайта рассматривается как отдельный ресурс. Могут возникнуть сложности с SSL сертификатом, необходимо заранее предусмотреть все возможные варианты в SAN DNS Host Name, или заказать сертификат с маской, например *.example.com.

Второй вариант наиболее практичный, выбор языка входит в URI, значит, не будет проблем с индексацией и копированием ссылки.

Третий вариант выглядит менее привычно, требует дополнительной логики при добавлении остальных GET параметров и может смутить пользователя при копировании ссылки. Не самый лучший вариант для публичных ссылок.
image
Я расскажу о реализации второго варианта на базе сервера NGINX. При минимальных изменениях можно применить описанные настройки и для первого варианта.

Настройка состоит из нескольких этапов.

Сначала проверяется языковая настройка браузера. Если у пользователя установлены cookie, то это значение переписывает настройку браузера. Итоговое значение передается в переменную $lang.

На первом этапе надо настроить back-end на получение GET параметра с информацией о языке. То есть реализуем третий вариант из списка, но внутри нашей системы. Для примера будем рассматривать GET параметр locale=<код локали>, используем двухбуквенный код ISO 639-1.

Надо удостовериться, что при переходе на ссылку типа http://<адрес_back-end_сервера>?locale=ru мы получает ответ на русском языке.
После этого можно настраивать NGINX на фронтенде.

Второй этап – получение языковых настроек от пользователя. Подразумевается, что при посещении сервер устанавливает cookie в браузере клиента с предпочтительным языком. Cookie называется $lang.

В конфигурации сайта пишем

map $http_accept_language $browser_lang {
        default en;
        ~ru ru;
}
map $cookie_lang $lang {
    default $browser_lang;
    ~en en;
    ~ru ru;
}

Сначала надо выделить запрос типа /NN/* в отдельный локейшен. Применяем регулярные выражения с выделением переменных.

location ~ '^/(?<lang_code>[\D-]{2})/(?<rest_uri>.*)'

Сохраняем двухсимвольный код в переменную $lang_code, все остальное в переменную $rest_uri

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

if ($lang_code ~* (uk|be)) {
                                return 301 http://$host/ru/$rest_uri$is_args$args;
                                }

Если код неизвестен, то используется английский вариант сайта.

if ($lang_code !~* (en|ru)) {
                                return 301 http://$host/en/$rest_uri$is_args$args;
                                }

Для if-конструкций порядок расположения имеет значение. Поэтому сначала надо ставить блок на проверку соответствия, и только в конце – на проверку несоответствия.

Далее надо очистить пользовательскую ссылку от возможного использования параметра locale в GET запросе. Неизвестно, как поведет себя back-end, если на него послать дублирующие аргументы, типа ?locale=en&locale=ru. Поэтому если пользователь пришел со ссылкой example.com/en/?locale=ru, то locale=ru на back-end лучше не посылать.

if ($args ~ (.*)locale=[^&]*(.*)) {
          set $args $1$2;
}

Убираем повторяющиеся амперсанды

 if ($args ~ (.*)&&+(.*)) {
         set $args $1&$2;
}

Убираем амперсанд в начале

if ($args ~ ^&(.*)) {
          set $args $1;
}

Убираем амперсанд в конце

if ($args ~ (.*)&$) {
          set $args $1;
}

Все, осталось только передать необходимые параметры на back-end. У меня в примере все идет на группу серверов, прописанных как back-end в разделе конфигурации upstream.

proxy_pass      http://back-end/$rest_uri?locale=$lang_code&$args;

Итоговая конфигурация выглядит примерно так
## get locale
map $http_accept_language $browser_lang {
        default en;
        ~ru ru;
}
map $cookie_lang $lang {
    default $browser_lang;
    ~en en;
    ~ru ru;
}

upstream back-end {
        ip_hash;
        server 172.21.71.15:8080; # vm-deb-osl-scala-1
        server 172.21.71.16:8080; # vm-deb-osl-scala-2
        server 172.21.71.17:8080; # vm-deb-osl-scala-3
        server 172.21.71.18:8080; # vm-deb-osl-scala-4
        keepalive 32;
}
server {
        listen  109.233.59.100:80;
        server_name  ruvpn.net;

location / {
# Redirect to locale
        return 301 http://$host/$lang$uri$is_args$args;
     }

# Handle URL with locale
location ~ '^/(?<lang_code>[\w-]{2})/(?<rest_uri>.*)' {
# Redirect to Russian for some CIS countries
                 if ($lang_code ~* (uk|be|kk)) {
                                return 301 http://$host/ru/$rest_uri$is_args$args;
                }
# Redirect to English for unknown languages
                if ($lang_code !~* (en|ru)) {
                                return 301 http://$host/en/$rest_uri$is_args$args;
                  }
	
                        if ($args ~ (.*)locale=[^&]*(.*)) {
                                set $args $1$2;
                                }
# Cleanup any repeated & introduced
                        if ($args ~ (.*)&&+(.*)) {
                                set $args $1&$2;
                                }
# Cleanup leading &
                        if ($args ~ ^&(.*)) {
                                set $args $1;
                                }
# Cleanup ending &
                        if ($args ~ (.*)&$) {
                                set $args $1;
                                }

   proxy_pass      http://back-end/$rest_uri?locale=$lang_code&$args;
   include         /etc/nginx/proxy.conf;
}

Можно проверить, как это работает на реальном сайте. Как вы уже заметили из примера конфигурации, по такой схеме настроен ресурс http://ruvpn.net. Все запросы типа ruvpn.net/ru/product/details/4/ будут отображать страницу на русском, в то время как запрос ruvpn.net/sv/product/details/4/ будет переадресован на ruvpn.net/en/product/details/4/, так как шведского варианта сайта не существует. При переходе на корневую ссылку ruvpn.net, произойдет автоматическая переадресация на ruvpn.net/ru/ или ruvpn.net/en/, в зависимости от ваших языковых настроек.
Единственным недостатком описанного метода является то, что нельзя использовать ссылки с двумя символами в начале URI для чего-то отличного от выбора языка. Но это вопрос архитектуры сайта и легко решается при проектировании.
Читать дальше
Twitter
Одноклассники
Мой Мир

материал с habrahabr.ru

3

      Add

      You can create thematic collections and keep, for instance, all recipes in one place so you will never lose them.

      No images found
      Previous Next 0 / 0
      500
      • Advertisement
      • Animals
      • Architecture
      • Art
      • Auto
      • Aviation
      • Books
      • Cartoons
      • Celebrities
      • Children
      • Culture
      • Design
      • Economics
      • Education
      • Entertainment
      • Fashion
      • Fitness
      • Food
      • Gadgets
      • Games
      • Health
      • History
      • Hobby
      • Humor
      • Interior
      • Moto
      • Movies
      • Music
      • Nature
      • News
      • Photo
      • Pictures
      • Politics
      • Psychology
      • Science
      • Society
      • Sport
      • Technology
      • Travel
      • Video
      • Weapons
      • Web
      • Work
        Submit
        Valid formats are JPG, PNG, GIF.
        Not more than 5 Мb, please.
        30
        surfingbird.ru/site/
        RSS format guidelines
        500
        • Advertisement
        • Animals
        • Architecture
        • Art
        • Auto
        • Aviation
        • Books
        • Cartoons
        • Celebrities
        • Children
        • Culture
        • Design
        • Economics
        • Education
        • Entertainment
        • Fashion
        • Fitness
        • Food
        • Gadgets
        • Games
        • Health
        • History
        • Hobby
        • Humor
        • Interior
        • Moto
        • Movies
        • Music
        • Nature
        • News
        • Photo
        • Pictures
        • Politics
        • Psychology
        • Science
        • Society
        • Sport
        • Technology
        • Travel
        • Video
        • Weapons
        • Web
        • Work

          Submit

          Thank you! Wait for moderation.

          Тебе это не нравится?

          You can block the domain, tag, user or channel, and we'll stop recommend it to you. You can always unblock them in your settings.

          • habrahabr.ru
          • домен habrahabr.ru

          Get a link

          Спасибо, твоя жалоба принята.

          Log on to Surfingbird

          Recover
          Sign up

          or

          Welcome to Surfingbird.com!

          You'll find thousands of interesting pages, photos, and videos inside.
          Join!

          • Personal
            recommendations

          • Stash
            interesting and useful stuff

          • Anywhere,
            anytime

          Do we already know you? Login or restore the password.

          Close

          Add to collection

             

            Facebook

            Ваш профиль на рассмотрении, обновите страницу через несколько секунд

            Facebook

            К сожалению, вы не попадаете под условия акции