Как вы определяете язык пользователя (в RoR), заданный в браузере? У меня будет поле выбора, которое пользователь может использовать в любое время, но я бы хотел по умолчанию использовать свой язык браузера.
Определение языка браузера в Rails
Ответ 1
2.6 Установка локали из информации, предоставленной клиентом
В конкретных случаях было бы целесообразно установить языковой стандарт из предоставленной клиентом информации, то есть не из URL-адреса. Эта информация может быть получена, например, с предпочтительного языка пользователей (установленного в их браузере), может основываться на географическом местоположении пользователей, выведенном из их IP-адреса, или пользователи могут предоставить его просто, выбрав язык в вашем интерфейсе приложения и сохраняя его профиль. Этот подход более подходит для веб-приложений или служб, а не для веб-сайтов - см. Раздел о сеансах, куках и архитектуре RESTful выше...
Одним из источников информации, предоставленной клиентом, будет HTTP-заголовок Accept-Language. Люди могут установить это в своем браузере или других клиентов (например, завиток)...
Другим способом выбора локали из клиентской информации будет использование базы данных для сопоставления клиентского IP-адреса в регионе, например GeoIP Lite Country...
Вы также можете предоставить пользователям своего приложения средства для установки (и, возможно, чрезмерной езды) языка в вашем прикладном интерфейсе, а также...
Ответ 2
Это старый вопрос, но я наткнулся на него как на душу в поисках ответов, и единственным доступным ответом была ссылка без какого-либо контекста. Так что здесь немного больше глубины, основанной на моем последующем копании.
Доступ к заголовку языка Accept-
request
объект request
в соответствующем контроллере:
request.env['HTTP_ACCEPT_LANGUAGE'] #returns nil or a string, e.g.:
# => "en-AU,en-US;q=0.7,en;q=0.3"
Это легкая часть, хотя. Чтобы использовать его в Rails, вам нужно проанализировать эту строку (или, может быть, это nil
?).
Боковая панель: учебник по заголовкам Accept- *
Итак, глядя на приведенный выше пример строки, некоторые языки имеют "q-значения" - относительный коэффициент качества, от 0 до 1. Более высокие значения q означают, что клиент предпочитает язык. Отсутствие q-значения действительно является самым высоким q-значением - неявным 1.0
(как с en-AU
в приведенной выше строке). Небольшое осложнение - браузер может отправлять вам языки с q-значениями, скажем, 0 - и я понимаю, что вы должны отказаться от этих языков, если это возможно.
Разбор заголовка языка Accept-
Имея это в виду, вот несколько разных, но похожих подходов, которые я рассмотрел для разбора такой строки в списке языков, упорядоченных по их q-значениям. С простым Ruby:
# to_s to deal with possible nil value, since nil.to_s => ""
langs = request.env['HTTP_ACCEPT_LANGUAGE'].to_s.split(",").map do |lang|
l, q = lang.split(";q=")
[l, (q || '1').to_f]
end
# => [["en-AU", 1.0], ["en-US", 0.7], ["en", 0.3]]
Или, если вы разбираетесь в регулярных выражениях, вы можете достичь того же, что и выше, и, возможно, одновременно улучшить свое усердное регулярное выражение:
rx = /([A-Za-z]{2}(?:-[A-Za-z]{2})?)(?:;q=(1|0?\.[0-9]{1,3}))?/
langs = request.env['HTTP_ACCEPT_LANGUAGE'].to_s.scan(rx).map do |lang, q|
[lang, (q || '1').to_f]
end
В любом случае, при необходимости вы можете выполнить что-то вроде:
# return array of just languages, ordered by q-value
langs.sort_by(&:last).map(&:first).reverse
# => ["en-AU", "en-US", "en"]
Я начал свой анализ с просмотра этой сути, но в итоге изменил ее довольно значительно. Регулярное выражение особенно отбрасывало совершенно хорошие вторичные локали, например, en-AU
стало en
, zh-TW
стало zh
. Я попытался исправить это с помощью моих изменений в этом регулярном выражении.
Ответ 3
Вот хорошо протестированный Ruby gem, который делает именно то, что вы хотите: https://github.com/ioquatix/http-accept
languages = HTTP::Accept::Language.parse("da, en-gb;q=0.8, en;q=0.7")
expect(languages[0].locale).to be == "da"
expect(languages[1].locale).to be == "en-gb"
expect(languages[2].locale).to be == "en"
Он имеет 100% -ный охват тестирования на широком диапазоне входных данных. Он возвращает языки в порядке, указанном соответствующими RFC.
Кроме того, если вы пытаетесь сопоставить язык пользователя с контентом, доступным в определенном наборе локалей, вы можете сделать следующее:
available_localizations = HTTP::Accept::Languages::Locales.new(["en-nz", "en-us"])
# Given the languages that the user wants, and the localizations available, compute the set of desired localizations.
desired_localizations = available_localizations & languages
Желаемые_локализации в приведенном выше примере представляют собой подмножество доступных_локализаций в соответствии с предпочтениями пользователя, доступными локализациями и рекомендациями RFC.
Ответ 4
Это действительно старый вопрос, но я хотел бы упомянуть, что в руководстве по Rails есть описание того, как определять язык браузера пользователя.
Приведенный ниже код основан на решении из руководства по Ruby on Rails с улучшениями:
- есть проверки HTTP_ACCEPT_LANGUAGE - иногда этот заголовок отсутствует для ботов, и вы получите ошибки в вашем инструменте отчетов об ошибках
- проверки - это язык, поддерживаемый вашим приложением
код:
def set_locale_based_on_browser
locale = extract_locale_from_accept_language_header
I18n.locale =
if locale_valid?(locale)
locale
else
:en
end
end
private
def locale_valid?(locale)
I18n.available_locales.map(&:to_s).include?(locale)
end
def extract_locale_from_accept_language_header
accept_language = request.env['HTTP_ACCEPT_LANGUAGE']
return unless accept_language
accept_language.scan(/^[a-z]{2}/).first
end
end
Дополнительную информацию об обнаружении языковых стандартов можно найти в руководстве по Ruby on Rails: https://guides.rubyonrails.org/i18n.html#choosing-an-implied-locale.
Ответ 5
Прошлой ночью я сделал этот крошечный драгоценный камень: accept_language
Он может быть интегрирован в приложение Rails следующим образом:
# app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
before_action :best_locale_from_request!
def best_locale_from_request!
I18n.locale = best_locale_from_request
end
def best_locale_from_request
return I18n.default_locale unless request.headers.key?('HTTP_ACCEPT_LANGUAGE')
string = request.headers.fetch('HTTP_ACCEPT_LANGUAGE')
locale = AcceptLanguage.intersection(string, I18n.default_locale, *I18n.available_locales)
# If the server cannot serve any matching language,
# it can theoretically send back a 406 (Not Acceptable) error code.
# But, for a better user experience, this is rarely done and more
# common way is to ignore the Accept-Language header in this case.
return I18n.default_locale if locale.nil?
locale
end
end
Я надеюсь, что это может помочь.