在 DEPS: Bump i18n from 1.14.8 to 1.15.2 - Pull Request #41242 - discourse/discourse - GitHub 中,我们将 ruby-i18n 更新到了 1.15.x,但该版本存在一个缺陷。
分析
首先,配置现在存储在 Fiber 上:
Fiber[:i18n_config]
新实现会检测当前 Fiber 是否继承了一个由其他 Fiber 拥有的配置:
if current.respond_to?(:owned_by?) && !current.owned_by?(Fiber.current)
current = current.dup
Fiber[:i18n_config] = current
end
问题出在 I18n::Config#initialize_copy 方法中:
def initialize_copy(other)
@owner = Fiber.current
end
它更改了复制后的配置的拥有者,但没有清除复制的 @locale,即子 Fiber 会继承父 Fiber 中显式设置的 @locale。
因此,如果父 Fiber 当前拥有:
I18n.locale == :zh_CN
子 Fiber 可能会继承一个仍然包含以下内容的复制配置:
@locale == :zh_CN
尽管该子 Fiber 现在代表一个不同的请求,该请求本应解析为英语。
这导致 Discourse 出现问题。当用户使用的显示语言与默认语言不同时,例如站点默认语言为中文,而显示语言为英语时,页面可能会意外地显示为中文,或者出现英语和中文混合的情况。
已提交一个 commit 回滚该版本更新,并添加了一些 spec。在等待上游修复之前,暂停更新可能是一个好主意。
4 个赞