如何通过URL更改区域设置?

时间:2014-10-12 14:35:35

标签: ruby-on-rails ruby localization

在我的双语Rails 4应用程序中,我有LocalesController这样:

class LocalesController < ApplicationController

  def change_locale
    if params[:set_locale]
      session[:locale] = params[:set_locale] 
      url_hash = Rails.application.routes.recognize_path URI(request.referer).path
      url_hash[:locale] = params[:set_locale]
      redirect_to url_hash
    end
  end

end

用户可以通过以下表单更改其语言环境:

def locale_switcher
  form_tag url_for(:controller => 'locales', :action => 'change_locale'), :method => 'get', :id => 'locale_switcher' do
  select_tag 'set_locale', options_for_select(LANGUAGES, I18n.locale.to_s)
end

这很有效。

但是,目前用户无法通过网址更改语言。

E.g。如果用户在页面www.app.com/en/projects上,然后手动将网址更改为www.app.com/fr/projects,则应该看到该页面的法语版本,但没有任何反应。

这在许多Rails应用程序中可能并不重要,但在我的应用程序中它非常重要。

如何解决?

感谢您的帮助。

3 个答案:

答案 0 :(得分:10)

这就是我在Rails 4应用程序之一中所做的:

config / routes.rb 中的

Rails.application.routes.draw do
  scope "(:locale)", locale: /#{I18n.available_locales.join("|")}/ do
    # rest of your routes here
    # for example:
    resources :projects
  end
end

确保在 config / environments / production.rb 中取消注释此行:

config.i18n.fallbacks = true

如果您希望设置除default_locale以外的:en设置,则在 config / application.rb 中取消注释此行:

config.i18n.default_locale = :de # and then :de will be used as default locale

现在,您的设置的最后一部分,在ApplicationController

中添加此方法
class ApplicationController < ActionController::Base
  # Prevent CSRF attacks by raising an exception.
  # For APIs, you may want to use :null_session instead.
  protect_from_forgery with: :exception

  before_action :set_locale

  private
    def set_locale
      I18n.locale = params[:locale] || session[:locale] || I18n.default_locale
      session[:locale] = I18n.locale
    end

   def default_url_options(options={})
     logger.debug "default_url_options is passed options: #{options.inspect}\n"
     { locale: I18n.locale }
   end
end

现在,您的应用可以通过以下方式访问:http://localhost:3000/en/projectshttp://localhost:3000/fr/projectshttp://localhost:3000/projects。最后一个http://localhost:3000/projects将使用:en作为其默认语言环境(除非您在application.rb中进行了此更改)。

答案 1 :(得分:2)

也许最好在routes.rb中设置区域设置,如下所示:

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

您可以在此处阅读更多内容http://guides.rubyonrails.org/i18n.html#setting-the-locale-from-the-url-params

UPD。如果您还将语言环境保存到会话,则还需要在每个请求中更新它。 您可以按照其他答案中的建议在过滤器中进行设置。但我更喜欢使用更少的过滤器:

def locale_for_request
  locale = params[:locale]
  if locale && I18n.locale_available?(locale)
    session[:locale] = locale
  else
    session[:locale] || I18n.default_locale
  end
end

# then use it in the around filter: I18n.with_locale(locale_for_request)

答案 2 :(得分:2)

如果您需要此行为,则必须在每次请求时将URL与会话进行比较。 你可能会这样做的一种方式是:

before_filter :check_locale
def check_locale
  if session[:locale] != params[:locale] #I'm assuming this exists in your routes.rb
    params[:set_locale] = params[:locale] #Generally bad to assign things to params but it's short for the example
    change_locale
  end
end