通过请求设置区域设置

在大多数情况下,你可能想要设置 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