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

在我的双语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 

这很有效。

但是,现在用户无法通过URL更改语言。

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

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

怎么修好?

谢谢你的帮助。

这就是我在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/projects ,或http://localhost:3000/projects 。 最后一个http://localhost:3000/projects将使用:en作为其默认语言环境(除非您在application.rb中进行了此更改)。

如果您需要此行为,则必须将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 

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

 # 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。 如果还将语言环境保存到会话,则还需要在每个请求中更新它。 您可以按照其他答案中的建议在filter中进行设置。 但我更喜欢使用更少的filter:

 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)