i18n-active_record添加call方法报stack level too deep错误如何修复
问题根因
触发stack level too deep (SystemStackError)是无限递归导致,核心问题有两个:
- 重写的
call方法内调用store_default_translations时,该方法内部会再次触发翻译查找逻辑,查找失败会再次进入当前call方法,循环往复直到栈溢出。 - 手动将自定义Missing模块include到
I18n::Backend::ActiveRecord的方式错误,破坏了i18n-active_record原有的异常处理链路。i18n-active_record本身会将Missing模块作为独立的异常处理器注册到I18n异常处理链,不需要手动混入后端类。
修复代码
module I18n module Backend class ActiveRecord module Missing # 保留原call方法逻辑别名,避免覆盖后丢失原有异常处理能力 alias_method :original_call, :call if method_defined?(:call) def call(exception, locale, key, options) if exception.is_a?(I18n::MissingTranslation) # 递归保护:正在处理该缺失翻译时直接返回空字符串,切断循环 return '' if options[:i18n_processing_missing] options[:i18n_processing_missing] = true begin store_default_translations(locale, key, options) ensure options.delete(:i18n_processing_missing) end # 可根据业务需求替换返回值,比如返回默认提示文本 '' else # 非缺失翻译类异常,走gem原有逻辑处理 original_call(exception, locale, key, options) end end end end end end
删除原有代码中I18n::Backend::ActiveRecord.send(:include, I18n::Backend::ActiveRecord::Missing)这一行,不需要手动执行模块注入。
关键说明
- 递归标记是解决栈溢出的核心:执行默认翻译存储逻辑前打上标记,存储过程中内部触发的二次翻译查找会识别到标记直接返回,不会重复进入缺失处理流程。
- 用alias保留原方法的非缺失异常处理分支,避免破坏gem原生的异常抛出、透传逻辑。
- 不要手动修改Missing模块的加载方式,i18n-active_record初始化时会自动完成异常处理器注册。
内容的提问来源于stack exchange,提问作者Alejandro Cortés
相关产品推荐
相关产品推荐

