[英]Why locale setting in Rails acts as global (when using Thin)?
我剛剛意識到推薦的Rails方法可以在控制器中設置區域設置
before_filter :set_locale
def set_locale
I18n.locale = params[:locale] || I18n.default_locale
end
全局設置區域設置。 上面的代碼有效,但我想知道default_locale
真的是默認的,如果你必須明確鍵入它?
我期望的是每個請求都有一個區域設置(就像我們有每個請求的會話一樣)並做類似的事情:
def set_locale
locale = params[:locale] if params[:locale]
end
並且默認情況下使用I18n.default_locale
。 這將理想地匹配路徑中的可選區域設置:
# config/routes.rb
scope "(:locale)", :locale => /en|nl/ do
resources :books
end
目前,如果出於某種原因我在某些操作中跳過了語言環境設置,它會使用上一個請求中設置的語言環境,該語言環境可能來自其他用戶!
並且沒有潛在的競爭條件,因為一個請求可以更改全局I18n.locale
而另一個請求(在I18n.locale
之前設置了另一個區域設置)處於渲染的中間?
更新:我現在發現的一些細節,來自I18n文件:
將當前語言環境設置為偽全局,即在Thread.current散列中def locale =(locale)
現在我想了解每個請求是否是一個單獨的線程。
更新2:請參閱我的答案以獲得解釋。
所以現在最后的答案。 TL; DR設置區域設置僅在使用線程Web服務器(如Thin和Puma)時才充當全局。
正如我所提到的, I18n.locale=
將當前語言環境設置為偽全局,即在Thread.current哈希中
因此它應該是按請求,並且它在Webrick和Unicorn中以這種方式工作。
但是如果你使用像Thin或Puma這樣的線程Web服務器,那么線程看起來會更長,並且為將來的請求保留該值,直到它被明確更改為止。 我從中學到的是來自新的Steve Klabnik的gem request_store :
如果你需要全局狀態,你可能已經達到了Thread.current。
<...>
所以人們正在使用那些花哨的線程Web服務器,比如Thin或Puma。 但是如果您使用Thread.current,並且您使用其中一個服務器,請注意! 值可能會比您預期的更長時間,這可能會導致錯誤。
上面的推薦代碼不會全局設置區域設置,它會按請求設置它。
before_filter :set_locale
def set_locale
I18n.locale = params[:locale] || I18n.default_locale
end
代碼通常放在BaseController中,因此在每個頁面呈現之前,它都會被觸發和設置。 沒有競爭條件,因為每個頁面都會觸發此代碼,並且將在那里計算I18n語言環境。 您可以將此擴展為使用英語來查找用戶區域設置,而不是會話區域設置,而不是請求參數。
def set_locale
I18n.locale = @user.locale || session[:locale] || params[:locale] || :en
end
換句話說,如果你在一個頁面上設置本地,讓我們在家庭控制器中說德語,並得到儀表板控制器,你會看到默認語言(英語)。 因為改變不是全球性的。 這就是代碼放在基本控制器中的原因。 希望它有意義。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.