Traduzindo Enums no Rails

Tutoriais - 10/Jun/2020 - por André Kanamura

Em desenvolvimento Web, aplicações Ruby on Rails possuem a gem Ruby I18n que oferece um framework para traduzir o sistema para um idioma personalizado ou dar suporte para múltiplas línguas. Depois de configurá-lo, basta definir os dicionários de traduções em arquivos no diretório config/locales/. Você pode encontrar arquivos prontos com traduções do Rails para diversos idiomas, como por exemplo para pt-BR aqui.

Apesar de facilitar bastante o trabalho de internacionalização, o Rails não possui uma forma bacana de traduzir Enums. Vamos considerar uma classe User que possui dois papéis :admin e :user, para "administradores" e "usuários comuns".

class User < ApplicationRecord
  enum role: { user: 0, admin: 10 }
end

O Rails Guides apresenta uma forma para lidar com tradução de models. Seguindo a estrutura para atributos aninhados, podemos listar as traduções para nossos papéis abaixo de model/attribute, sendo nosso model user e o atributo role. Para o nosso exemplo, podemos definir nosso dicionário da seguinte maneira:

pt-BR:
  activerecord:
    attributes:
      user/role:
        admin: "Administrador"
        user: "Usuário"

Agora nas views podemos chamar o método human_attribute_name na classe, passando para ele o atributo que quer traduzir. Nosso exemplo ficaria mais ou menos assim:

# user = User.new(role: :admin)

User.human_attribute_name("role.#{user.role}")
# => "Administrador"

Procurando uma forma alternativa para implementar a tradução de enums, encontrei essa solução no Stack Overflow. A proposta consiste em criar nosso próprio método de tradução, semelhante ao human_attribute_name apresentado na documentação do Rails. Considerando a mesma classe User do exemplo acima, definimos nosso dicionário da seguinte forma:

pt-BR:
  activerecord:
    attributes:
      user:
        roles:
          admin: 'Administrador'
          user: 'Usuário'

Dessa forma os papéis estão descritos dentro dos atributos de User no nosso dicionário. Agora precisamos implementar o método que vai aplicar a tradução. Como models herdam de ApplicationRecord, podemos implementá-lo da seguinte forma:

class ApplicationRecord < ActiveRecord::Base
  self.abstract_class = true

  def self.human_enum_name(enum_name, enum_value)
    I18n.t("activerecord.attributes.#{model_name.
           i18n_key}.#{enum_name.to_s.pluralize}.#{enum_value}")
  end
end

Assim, o método fica disponível para qualquer model e pode ser usado com diferentes enums. Por fim, nas views podemos chamar o método criado para traduzir o Enum:

User.human_enum_name(:role, :admin)
# => "Administrador"

# user = User.new(role: :admin)
<%= User.human_enum_name(:role, user.role) %>

Pessoalmente, apesar de simples, acho pouco atraente a forma padrão do Rails de implementar a tradução de enums. No entanto, a flexibilidade do framework permite essa solução alternativa para o problema. Ficam aí descritas as duas alternativas para você escolher a que for mais conveniente para você.

Referências

Foto de perfil do autor
André Kanamura

Dev na Campus Code