设计和I18n – 重置密码路由问题

我将I18n添加到我正在使用Devise的RoR应用程序中,如果我尝试重置密码,我现在收到错误。 错误是:

Routing Error No route matches {:action=>"edit", :controller=>"devise/passwords", :reset_password_token=>"uMopWesaxczNn2cdePUQ"} 

如何才能正确设置我的Devise路由以计入I18n?

的routes.rb

  scope ":locale", locale: /#{I18n.available_locales.join("|")}/ do devise_for :users, path_names: {sign_in: "login", sign_out: "logout"}, controllers: {omniauth_callbacks: "omniauth_callbacks"} root to: 'static_pages#home' end match '*path', to: redirect {|params| "/#{I18n.default_locale}/#{CGI::unescape(params[:path])}" }, constraints: lambda { |req| !req.path.starts_with? "/#{I18n.default_locale}/" } match '', to: redirect("/#{I18n.default_locale}") 

application_controller.rb

 before_filter :set_locale def set_locale I18n.locale = params[:locale] if params[:locale].present? end def default_url_options(options = {}) {locale: I18n.locale} end 

我确实为这种情况创建了一个示例应用程序 (设计+国际化)。 自从我创建该应用程序以来,它已经是时候了,可能它有点小错误/不完整,但关键是使用带括号的可选范围。

你的代码, devise_for :users的问题没有定义你没有:locale变量集(这是我猜你的错误,路由中的重定向代码可能不起作用 – 你真的不需要,我没有测试,但我不认为这是一个很好的做法)。 此外,这就是为什么它试图将标记值分配为:locale变量。

相反,您需要使用括号。 这样:locale将是可选的,并且在以下情况下您的路由定义仍然有效:locale未设置:locale

 scope "(:locale)", :locale => /en|tr/ do devise_for :users root :to => "main#index" end 

我希望它有所帮助。

我遇到了同样的问题(在密码重置时出现路由错误),但这是我找到的解决方案:路由错误不是由控制器或任何其他Devise内部进程引起的,而是由视图引起的。 在views/devise/mailer/reset_password_instructions.html.erb中:

 <%= link_to 'Change my password', edit_password_url(@resource, :reset_password_token => @resource.reset_password_token) %> 

需要更换为:

 <%= link_to 'Change my password', edit_password_url(@resource, :reset_password_token => @resource.reset_password_token, :locale => I18n.locale) %>` 

我不知道为什么默认情况下不添加locale参数。

我对设置Devise并不是很了解,但我确实花了一些时间来研究Rails路由的国际化,所以希望这个答案对你有用,如果不是你的问题的答案,那么作为一个更接近答案的参考(内容主要是我在i18n Railscast的评论中写的评论的重述 ,这也是Rails i18n路由信息的一个很好的来源):

你的application_controller.rb看起来很好,但也许尝试更改你的routes.rb看起来像这样:

config / routes.rb (示例)

 MyApp::Application.routes.draw do scope ":locale", locale: /#{I18n.available_locales.join("|")}/ do # ... match '/about', to: 'static_pages#about' # handles /valid-locale root to: 'static_pages#home', as: "locale_root" # handles /valid-locale/fake-path match '*path', to: redirect { |params, request| "/#{params[:locale]}" } end # handles / root to: redirect("/#{I18n.default_locale}") # handles /bad-locale|anything/valid-path match '/*locale/*path', to: redirect("/#{I18n.default_locale}/%{path}") # handles /anything|valid-path-but-no-locale match '/*path', to: redirect("/#{I18n.default_locale}/%{path}") end 

由于有两个root_paths ,我在:locale范围内重命名了一个,因此应用程序和测试中不会发生冲突。 我使用RSpec测试路线如下:

规格/路由/ routing_spec.rb

 require 'spec_helper' describe "Routes" do describe "locale scoped paths" do I18n.available_locales.each do |locale| describe "routing" do it "should route /:locale to the root path" do get("/#{locale.to_s}"). should route_to("static_pages#home", locale: locale.to_s) end end describe "redirecting", type: :request do subject { response } context "fake paths" do let(:fake_path) { "fake_path" } before { get "/#{locale.to_s}/#{fake_path}" } it { should redirect_to(locale_root_path(locale)) } end end end end describe "non-locale scoped paths" do describe "redirecting", type: :request do subject { response } context "no path given" do before { get "/" } it { should redirect_to(locale_root_path(I18n.default_locale)) } end context "a valid action" do let(:action) { "about" } let!(:default_locale_action_path) { about_path(I18n.default_locale) } context "with a valid but unsupported locale" do let(:unsupported_locale) { "fr" } before { get "/#{unsupported_locale}/#{action}" } it { should redirect_to(default_locale_action_path) } end context "with invalid information for the locale" do let(:invalid_locale) { "invalid" } before { get "/#{invalid_locale}/#{action}" } it { should redirect_to(default_locale_action_path) } end context "with no locale information" do before { get "/#{action}" } it { should redirect_to(default_locale_action_path) } end end context "invalid information" do let(:invalid_info) { "invalid" } before { get "/#{invalid_info}" } it { should redirect_to("/#{I18n.default_locale}/#{invalid_info}") } # This will then get caught by the "redirecting fake paths" condition # and hence be redirected to locale_root_path with I18n.default_locale end end end end