Posted at

HTTPリクエストヘッダのAccept-Languageから動的にI18n.localeを変更する。

More than 5 years have passed since last update.


環境


shell

$ gem -v

2.1.11
$ ruby -v
2.0.0 (2013-06-27 patchlevel 247) [x86_64-linux]
$ rails -v
Rails 3.2.15
$ bundle -v
Bundler version 1.3.5


実装


Gemfile

# 全てのGroupに属すように追加する。

gem 'http_accept_language'


config/application.rb

@@ -40,6 +40,10 @@ class Application < Rails::Application

# The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded.
# config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s]
# config.i18n.default_locale = :de
+ config.i18n.default_locale = :en
+
+ # see:http://batsov.com/articles/2012/09/12/setting-up-fallback-locale-s-in-rails-3/
+ config.i18n.fallbacks = [:en]

@@ -83,5 +87,20 @@ class Application < Rails::Application

+ # Setting for http_accept_language
+ class HTTPAcceptLanguageToI18nLocale
+ def initialize(app)
+ @app = app
+ end
+
+ def call(env)
+ I18n.locale = env.http_accept_language.compatible_language_from(I18n.available_locales)
+ @app.call(env)
+ end
+ end
+
+ config.middleware.use HttpAcceptLanguage::Middleware
+ config.middleware.use HTTPAcceptLanguageToI18nLocale


※ LINE Numberは環境により異なります。



  • config.i18n.fallbacksにAccept-Languageに有効でないロケール情報が入っていた場合のデフォルト値を設定する。


  • compatible_language_fromは、引数に指定されたロケールの中からHTTP_ACCEPT_LANGUAGEに指定されたロケールにマッチした値を返す。


  • config.middleware.use HTTPAcceptLanguageToI18nLocaleの前にconfig.middleware.use HttpAcceptLanguage::Middlewareと記述すること。こうすることにより、envhttp_accept_languageが追加される。


結果


pry

3.2.15@2.0.0 (main)> I18n.available_locales

=> [
[ 0] :en,
[ 1] :"en-gb",
[ 2] :"pt-br",
[ 3] :"en-us",
[ 4] :"en-bork",
[ 5] :"en-ind",
[ 6] :fr,
[ 7] :nl,
[ 8] :pl,
[ 9] :"en-au",
[10] :"en-ca",
[11] :sk,
[12] :ja,
[13] :"nb-no",
[14] :es,
[15] :vi,
[16] :de,
[17] :"de-ch"
]

3.2.15@2.0.0 (main)> env.http_accept_language
=> #<HttpAcceptLanguage::Parser:0x007f21062d2e58 @header="en", @user_preferred_languages=["en"]>
3.2.15@2.0.0 (main)> I18n.locale
=> :en

3.2.15@2.0.0 (main)> env.http_accept_language
=> #<HttpAcceptLanguage::Parser:0x007f210d45a990 @header="fr", @user_preferred_languages=["fr"]>
3.2.15@2.0.0 (main)> I18n.locale
=> :fr

3.2.15@2.0.0 (main)> env.http_accept_language
=> #<HttpAcceptLanguage::Parser:0x007f210e234a48 @header="it", @user_preferred_languages=["it"]>
3.2.15@2.0.0 (main)> I18n.locale
=> :en