0
Help us understand the problem. What are the problem?

posted at

updated at

Rubyで言語ネゴシエーション

世の中には多くの言語、方言、書記体系がある。幸い、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で、言語ネゴシエーションの処理を楽しもう!🌐

Register as a new user and use Qiita more conveniently

  1. You can follow users and tags
  2. you can stock useful information
  3. You can make editorial suggestions for articles
What you can do with signing up
0
Help us understand the problem. What are the problem?