Rails中Helper方法获取的I18n翻译值AJAX加载后不随语言更新
问题原因分析
嘿,这个问题我之前在项目里也踩过坑!核心问题出在Ruby常量的缓存特性和I18n的求值时机上:
- Ruby常量的一次性求值:
EMPLOYMENT_TYPE作为常量,在模型第一次被加载时就会执行里面的I18n.t方法,把翻译结果直接缓存成常量的固定值。之后不管你怎么切换语言,这个常量都不会重新初始化,所以始终返回第一次加载时的语言翻译。 - AJAX请求的上下文局限:当你切换语言后触发AJAX请求,服务器渲染
employment_list.js.erb时,调用的还是已经缓存好的常量值,并不会重新根据当前请求的I18n.locale去执行I18n.t。
解决方法
我整理了几个实用的方案,你可以根据项目情况选择:
方案1:把常量改为类方法(推荐)
放弃使用常量,改用类方法来动态返回翻译值,这样每次调用都会根据当前请求的语言重新计算:
# 在你的模型里 class YourModel < ApplicationRecord def self.employment_types { full_time: I18n.t('employment_types.full_time'), part_time: I18n.t('employment_types.part_time'), contract: I18n.t('employment_types.contract') } end end
然后在Helper或视图里调用这个类方法:
# Helper里 def employment_type_options YourModel.employment_types.map { |key, value| [value, key] } end
这样每次AJAX请求时,都会重新执行I18n.t,拿到当前语言的最新翻译。
方案2:用延迟求值的Proc/lambda保留类似常量的结构
如果你一定要保留类似常量的写法,可以用lambda包裹I18n.t,每次使用时手动调用执行:
# 模型里的定义 EMPLOYMENT_TYPE = { full_time: -> { I18n.t('employment_types.full_time') }, part_time: -> { I18n.t('employment_types.part_time') }, contract: -> { I18n.t('employment_types.contract') } }.freeze
使用的时候要调用lambda的call方法:
# 在视图或Helper里 EMPLOYMENT_TYPE[:full_time].call()
这种方式既保留了类似常量的结构,又能每次获取最新的翻译值。
方案3:确保AJAX请求传递locale参数(配合前两种方案)
另外要确认你的AJAX请求会带上当前的locale参数,这样服务器端能正确设置I18n.locale。可以在application_controller里设置全局的locale拦截:
class ApplicationController < ActionController::Base before_action :set_locale private def set_locale I18n.locale = params[:locale] || I18n.default_locale end # 确保所有URL都带上locale参数 def default_url_options { locale: I18n.locale } end end
这样切换语言后,AJAX请求会自动带上locale参数,服务器端就能识别当前语言,配合前面的方案就能返回正确的翻译。
内容的提问来源于stack exchange,提问作者Kingsley Simon
相关产品推荐
相关产品推荐

