通過請求設定區域設定

在大多數情況下,你可能想要設定 I18n 語言環境。有人可能想要為當前會話,當前使用者或基於 URL 引數設定區域設定這可以通過在你的一個控制器中實現 before_action,或者在 ApplicationController 中實現,以便在所有控制器中實現。

class ApplicationController < ActionController::Base
  before_action :set_locale

  protected

  def set_locale
    # Remove inappropriate/unnecessary ones
    I18n.locale = params[:locale] ||    # Request parameter
      session[:locale] ||               # Current session
      (current_user.preferred_locale if user_signed_in?) ||  # Model saved configuration
      extract_locale_from_accept_language_header ||          # Language header - browser config
      I18n.default_locale               # Set in your config files, english by super-default
  end

  # Extract language from request header
  def extract_locale_from_accept_language_header
    if request.env['HTTP_ACCEPT_LANGUAGE']
      lg = request.env['HTTP_ACCEPT_LANGUAGE'].scan(/^[a-z]{2}/).first.to_sym
      lg.in?([:en, YOUR_AVAILABLE_LANGUAGES]) ? lg : nil
    end
  end

基於 URL

locale param 可能來自這樣的 URL

http://yourapplication.com/products?locale=en

要麼

http://yourapplication.com/en/products

要實現後者,你需要編輯你的 routes,新增一個 scope

# config/routes.rb
scope "(:locale)", locale: /en|fr/ do
  resources :products
end

通過這樣做,訪問 http://yourapplication.com/en/products 會將你的語言環境設定為:en。相反,訪問 http://yourapplication.com/fr/products 將把它設定為:fr。此外,丟失:locale 引數時不會出現路由錯誤,因為訪問 http://yourapplication.com/products 將載入預設的 I18n 語言環境。

基於會話或基於永續性

這假設使用者可以單擊按鈕/語言標誌來更改語言。該操作可以路由到將會話設定為當前語言的控制器(如果使用者已連線,最終會將更改保留到資料庫)

class SetLanguageController < ApplicationController
  skip_before_filter :authenticate_user!
  after_action :set_preferred_locale

  # Generic version to handle a large list of languages
  def change_locale
    I18n.locale = sanitize_language_param
    set_session_and_redirect
  end

你必須使用可用語言列表定義 sanitize_language_param,並在語言不存在時最終處理錯誤。

如果你的語言非常少,則可能需要將其定義為:

def fr
  I18n.locale = :fr
  set_session_and_redirect
end

def en
  I18n.locale = :en
  set_session_and_redirect
end

private

  def set_session_and_redirect
    session[:locale] = I18n.locale
    redirect_to :back
  end

  def set_preferred_locale
    if user_signed_in?
      current_user.preferred_locale = I18n.locale.to_s
      current_user.save if current_user.changed?
    end
  end
end

注意:不要忘記為 change_language 操作新增一些路由

預設區域設定

請記住,你需要設定應用程式預設區域設定。你可以通過在 config/application.rb 中設定它來實現:

config.i18n.default_locale = :de

或者通過在 config/initializers 資料夾中建立初始化程式:

# config/initializers/locale.rb
I18n.default_locale = :it