2

我添加了I18n到我正在使用Devise的RoR應用程序,如果我嘗試執行密碼重設,我現在正在收到錯誤。錯誤是:Devise和I18n - 重置密碼路由問題

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 

回答

8

我沒有創建一個sample app正是針對這種情況(設計+國際化)。自從我創建該應用程序以來,已經有很長一段時間了,可能它幾乎沒有錯誤/不完整,但關鍵點是使用帶括號的可選範圍。

與您的代碼的問題,devise_for :users當你沒有:locale變量集合沒有定義(這是林從你的錯誤猜測,在你的路由重定向代碼可能無法正常工作 - 你真的不需要的是,我沒有測試,但我不認爲這是一個很好的做法)。此外,這就是爲什麼它試圖將令牌值分配爲:locale變量。

相反,您需要使用圓括號。因此:locale將是可選的,並且當未設置:locale時,您的路線定義將保持有效。

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

我希望它有幫助。

+0

哇,謝謝!令人驚訝的是,一組缺失的括號給我帶來了很多麻煩。 – diasks2 2012-08-13 12:42:02

+1

我很高興它確實有幫助!此功能在Rail i18n文檔指南中有記錄,但有一點難以注意:) – 2012-08-13 14:32:16

+0

這肯定有助於解決問題 - 但這不會導致另一個問題 - 即重複的URL?如果使用括號,則所有語言環境都不允許使用。因此,可以通過多個Url訪問相同的內容.... – 2014-03-29 05:08:41

0

我真的不知道很多關於建立設計,但我確實花了一些時間在看到Rails路由國際化,所以希望這個答案對你有用,如果不是作爲你的問題的答案,那麼作爲接近答案的參考(內容大部分是re

application_controller.rb看起來好像沒什麼問題,但也許嘗試改變你的的routes.rb看起來是這樣的:一個評論我寫in the comments for the i18n Railscast,這也是Rails的國際化路由信息的良好來源)的散列此:

配置/ 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,我改名內的一個0範圍,所以在應用程序和測試中不會有衝突。我測試使用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 
+0

謝謝你的回答保羅;但是,即使我按照您的建議更改了我的routes.rb,我仍然收到相同的錯誤。我認爲我的問題更多與Devise相關,以及如何正確覆蓋密碼重置路由。 – diasks2 2012-08-12 15:52:21

+0

不用擔心。我希望擁有Devise專業知識的人能夠爲您提供所需的信息! – 2012-08-12 15:55:12

+0

嗨保羅。在測試你的例子之後。我認爲我的問題不一定與Devise有關。我試着用你的routes.rb例子和一個普通的password_resets_controller(就像在Railscasts的第274集中使用的例子一樣)。在這種情況下,我仍然在嘗試傳遞reset_password_token作爲語言環境參數''Routing Error No route matches {:action =>「edit」,:controller =>「password_resets」,:locale =>「 1qbkCGXrNx3tLkqCGvMrHw「}'你是否得到了密碼重置以正確使用I18n?如果是這樣,你會介意展示一些示例代碼嗎? – diasks2 2012-08-13 02:57:43

2

我有同樣的問題(獲取密碼重置路由錯誤),但這裏是我找到的解決方案: 路由錯誤不是由控制器或任何其他設計內部進程,但由視圖引起的。在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) %>` 

我不知道爲什麼語言環境參數默認情況下不添加。