世の中には多くの言語、方言、書記体系がある。幸い、BCP 47 仕様には、それらを識別するためのタグが用意されており、Accept-Language
ヘッダー を使用すると、ユーザーは自分が好む言語を一覧で提示できる。
たとえば、日本語を母国語とする人は、ブラウザを次の値に設定できる:
Accept-Language: ja
関西弁を好むなら:
Accept-Language: ja-KS, ja;q=0.9
それらが表示できない場合、ユーザーはタイ語ならわかるとする。ただしタイ字は読めないのでローマ字が必要という場合:
Accept-Language: ja-KS, ja;q=0.9, th-Latn;q=0.8
最後に、フランス語とドイツ語はわからないので、必要に応じて別の言語にフォールバックして欲しい場合:
Accept-Language: ja-KS, ja;q=0.9, th-Latn;q=0.8, *;q=0.1, fr;q=0, de;q=0
Rubyには、そのためのaccept_language
がある:
日本語(:ja
)と韓国語(:ko
)に翻訳できるサーバーの場合、accept_language
を使えばユーザーが好む言語一覧との共通部分を見つけることができる。これによりサーバーはユーザーのために日本語を選択できる:
AcceptLanguage.parse("ja-KS, ja;q=0.9, th-Latn;q=0.8, *;q=0.1, fr;q=0, de;q=0").match(:ko, :ja) # => :ja
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.parse(string).match(*I18n.available_locales)
# サーバーが一致する言語を何も提供できない場合は、
# 理論的には 406 (Not Acceptable) エラーコードを送り返すことができます。
# しかし、ユーザーの使い勝手をより良くするため、これはほとんど行われておらず、
# このような場合には一般に Accept-Language ヘッダーを無視するという方法が採られます。
return I18n.default_locale if locale.nil?
locale
end
end
Rubyで、言語ネゴシエーションの処理を楽しもう!🌐