如何通过URL更改区域设置?
在我的双语轨道4应用程序,我有一个LocalesController
这样的:如何通过URL更改区域设置?
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更改语言。
E.g.如果用户在页面www.app.com/en/projects
上,然后手动将URL更改为,他应该请参阅该页面的法语版本,但没有任何反应。
这在许多Rails应用程序中可能并不重要,但在我的系统中它非常重要。
如何解决?
感谢您的任何帮助。
这是我如何做它的轨道4,5应用之一:
在的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
如果您希望有比:en
以外的default_locale
设置,然后在的config/application.rb中,取消这条线:
config.i18n.default_locale = :de # and then :de will be used as default locale
现在,您设置的最后一部分,加入ApplicationController
这种方法:http://localhost:3000/en/projects
,http://localhost:3000/fr/projects
,或http://localhost:3000/projects
:现在
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/projects
将使用:en
作为其默认语言环境(除非您在application.rb中进行此更改)。
事实证明,这工作得很好。我认为关键是要始终执行一个会议,不管是谁或什么。这样正确的语言环境始终保持不变。这是我之前错过的。 – Tintin81 2014-12-23 09:48:53
我错过了这里的东西,当我做了上述我得到了以下'http:// localhost:3000/sign_in?locale = en' – 2016-05-19 11:34:05
也许是更好的设置区域中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)
是的,我已经有了。我读了所有的指南。 – Tintin81 2014-11-01 21:34:36
@ Tintin81我同意prcu,如果你想让URL定义'true'语言环境,你应该使用在路由中设置的URL的语言环境。如果它仍然在URL中,将它重新写回会话并没有什么意义。 – BookOfGreg 2014-11-01 23:49:16
@ Tintin81如果您在rotes中使用可选语言环境,那么是的,您可以将语言环境保存到会话中。这将有助于为没有区域设置的url返回用户的语言环境。我已经更新了这个案例的答案。 – prcu 2014-11-02 09:05:33
如果您想要这种行为,您将不得不每次请求都会根据会话比较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
您需要检查并调整适当的路由规则以处理特定于语言环境的路径。 – 2014-10-12 16:11:05