You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用I18n翻译Enum用于Select?现有Enum翻译代码能否优化?

使用I18n翻译Enum适配Select组件的最佳方式及代码优化

问题描述

请问使用I18n翻译Enum以适配Select组件的最佳方式是什么?此外,当前这段生成带翻译的Enum哈希的代码是否有更优写法?

现有代码:

class ApplicationRecord < ActiveRecord::Base
  def self.translate_enum(enum)
    self.send(enum.to_s).map do |key, value|
      { self.human_enum_name(enum, key) => value }
    end.reduce(:merge)
  end
end
class EnumerableObject < ApplicationRecord
  enum sales_exception: { without: 0, income: 1, commitment: 2, restriction: 3 }, _suffix: true
end

调用结果:EnumerableObject.translate_enum(:sales_exception) => {"Sem Exceção"=>0, "Exceção Renda"=>1, "Exceção Comprometimento"=>2, "Exceção Restrição"=>3}


最佳实践:用I18n翻译Enum适配Select组件

首先,Rails本身就为Enum翻译提供了原生支持,完全不需要额外造轮子,核心就是你已经用到的human_enum_name方法,配合标准的I18n配置就能完美适配Select组件:

  1. 配置翻译文件
    首先在对应语言的locale文件(比如config/locales/pt-BR.yml,因为你的翻译是葡萄牙语)中添加Enum的翻译:

    pt-BR:
      activerecord:
        attributes:
          enumerable_object:
            sales_exception:
              without: "Sem Exceção"
              income: "Exceção Renda"
              commitment: "Exceção Comprometimento"
              restriction: "Exceção Restrição"
    

    这个结构是Rails约定的:activerecord.attributes.模型名.枚举名.枚举键,Rails会自动识别并在调用human_enum_name时返回对应的翻译。

  2. 在Select组件中使用
    你当前方法返回的哈希结构(翻译文本为键,Enum值为值)正好是Rails表单助手select或options_for_select需要的格式,直接传入即可:

    <%# 在表单中使用 %>
    <%= form.select :sales_exception, EnumerableObject.translate_enum(:sales_exception) %>
    

代码优化:简化翻译Enum哈希的实现

你当前的代码用map生成单个键值对的哈希,再用reduce(:merge)合并,虽然能工作,但可以更简洁高效,推荐两种优化写法:

方案1:利用transform_keys一键转换

class ApplicationRecord < ActiveRecord::Base
  def self.translate_enum(enum_name)
    send(enum_name.to_s).transform_keys { |key| human_enum_name(enum_name, key) }.to_h
  end
end
  • 逻辑很直接:遍历Enum的所有键,把每个键替换成对应的翻译文本,最后用to_h确保返回标准哈希(Rails的Enum本身是哈希,这一步可选,但显式写出来更清晰)。

方案2:用each_with_object构建哈希

如果觉得transform_keys不够直观,也可以用each_with_object来逐步构建哈希:

class ApplicationRecord < ActiveRecord::Base
  def self.translate_enum(enum_name)
    send(enum_name.to_s).each_with_object({}) do |(key, value), hash|
      hash[human_enum_name(enum_name, key)] = value
    end
  end
end
  • 这个写法更直白:初始化一个空哈希,然后把每个翻译后的键和对应的值存入哈希,避免了创建多个临时哈希再合并的额外开销,性能更好,尤其是当Enum选项较多时。

为什么这两种写法更优?

  • 可读性更强:直接表达了“转换Enum键为翻译文本,保留原值”的意图,不需要理解map+reduce的组合逻辑。
  • 性能更高:一次遍历完成所有操作,没有额外的哈希合并步骤。
  • 更符合Ruby/Rails风格:利用Ruby的哈希方法简化代码,更优雅简洁。

内容的提问来源于stack exchange,提问作者Marlon Henry Schweigert

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:19:55