RailsでI18n.localeを書き換えてたらたまに言語設定がバグる問題に遭遇した
他のユーザー(:en)で画面を参照したあとに元のユーザー(:ja)で画面を見ると、稀にlocale=:enで画面が表示されてしまうという問題に遭遇しました。
実装はこんな感じ。
class HogeController < ApplicationController
before_action :set_locale
def set_locale
I18n.locale = current_user.locale || I18n.default_locale
end
end
Railsガイドでもだいたいおんなじ感じのコードが乗ってる。ApplicationControllerに書いて全コントローラーに継承させるのならこれでもいけるんですが、継承されないコントローラーにアクセスした場合に他のユーザーが設定したロケールになってしまう事があった。
こんなPull RequestもありI18nはスレッドセーフだと言っていますが、
スレッドセーフなだけで、after_actionとかで元の言語に戻しておいてあげないと次に同じスレッドを使ったときに変更されたままの言語が使われてしまうといった感じなんだと思われます。
(違うコントローラーなどでset_localeが実行されない場合に起こる)
こんなふうに実装を変えたら解消しました。
class HogeController < ApplicationController
around_action :set_locale
def set_locale
locale = current_user.locale || I18n.default_locale
I18n.with_locale locale do
yield
end
end
end
I18n.with_locale
を使うことにより、ロケールの変更をアクション実行時に限定しました。
after_action
でもとに戻すでも行けると思いますが、こっちのほうがドヤり感が高い。
around_action 初めて使った。