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ê.