2014-10-12 29 views
3

在我的雙語軌道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應用程序中可能並不重要,但在我的系統中它非常重要。

如何解決?

感謝您的任何幫助。

+0

您需要檢查並調整適當的路由規則以處理特定於語言環境的路徑。 – 2014-10-12 16:11:05

回答

6

這是我如何做它的軌道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/projectshttp://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中進行此更改)。

+0

事實證明,這工作得很好。我認爲關鍵是要始終執行一個會議,不管是誰或什麼。這樣正確的語言環境始終保持不變。這是我之前錯過的。 – Tintin81 2014-12-23 09:48:53

+0

我錯過了這裏的東西,當我做了上述我得到了以下'http:// localhost:3000/sign_in?locale = en' – 2016-05-19 11:34:05

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) 
+0

是的,我已經有了。我讀了所有的指南。 – Tintin81 2014-11-01 21:34:36

+1

@ Tintin81我同意prcu,如果你想讓URL定義'true'語言環境,你應該使用在路由中設置的URL的語言環境。如果它仍然在URL中,將它重新寫回會話並沒有什麼意義。 – BookOfGreg 2014-11-01 23:49:16

+1

@ Tintin81如果您在rotes中使用可選語言環境,那麼是的,您可以將語言環境保存到會話中。這將有助於爲沒有區域設置的url返回用戶的語言環境。我已經更新了這個案例的答案。 – prcu 2014-11-02 09:05:33

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 
相關問題