簡體   English   中英

為什么Rails中的語言環境設置充當全局(使用Thin時)?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM