修复:由于近期 ruby-i18n 更新导致的 I18n 回归问题

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 个赞

感谢反馈,我正在查看。

4 个赞