NOTA: El marco Ruby I18n le proporciona todos los medios necesarios para la internacionalización/localización de su aplicación de Rails. También puede usar varias gemas disponibles para agregar funcionalidad o características adicionales. Consulte la gema rails-i18n para obtener más información.
1 Cómo funciona I18n en Ruby on Rails
La internacionalización es un problema complejo. Los idiomas naturales difieren en tantas formas (por ejemplo, en las reglas de pluralización) que es difícil proporcionar herramientas para resolver todos los problemas de una vez. Por esa razón, la API de I18n de Rails se centra en:
- proporcionar soporte para inglés y otros idiomas similares de forma predeterminada
- facilitar la personalización y extensión de todo para otros idiomas
Como parte de esta solución, todas las cadenas estáticas en el marco de Rails (por ejemplo, mensajes de validación de Active Record, formatos de hora y fecha) han sido internacionalizadas. La localización de una aplicación de Rails implica definir valores traducidos para estas cadenas en los idiomas deseados.
Para localizar, almacenar y actualizar contenido en su aplicación (por ejemplo, traducir publicaciones de blog), consulte la sección Traducción de contenido del modelo.
1.1 La arquitectura general de la biblioteca
Por lo tanto, la gema Ruby I18n se divide en dos partes:
- La API pública del marco I18n, un módulo Ruby con métodos públicos que definen cómo funciona la biblioteca.
- Un backend predeterminado (que se llama intencionalmente backend Simple) que implementa estos métodos.
Como usuario, siempre debe acceder solo a los métodos públicos en el módulo I18n, pero es útil conocer las capacidades del backend.
NOTA: Es posible cambiar el backend Simple incluido por uno más potente, que almacene los datos de traducción en una base de datos relacional, un diccionario GetText u otro similar. Consulte la sección Uso de diferentes backends a continuación.
1.2 La API pública de I18n
Los métodos más importantes de la API de I18n son:
translate # Buscar traducciones de texto
localize # Localizar objetos de fecha y hora en formatos locales
Estos tienen los alias #t y #l, por lo que puede usarlos de la siguiente manera:
I18n.t 'store.title'
I18n.l Time.now
También hay lectores y escritores de atributos para los siguientes atributos:
load_path # Anunciar sus archivos de traducción personalizados
locale # Obtener y establecer la configuración regional actual
default_locale # Obtener y establecer la configuración regional predeterminada
available_locales # Configuraciones regionales permitidas disponibles para la aplicación
enforce_available_locales # Aplicar permisos de configuración regional (verdadero o falso)
exception_handler # Usar un manejador de excepciones diferente
backend # Usar un backend diferente
Entonces, ¡vamos a internacionalizar una aplicación de Rails simple desde cero en los próximos capítulos!
2 Configurar la aplicación de Rails para la internacionalización
Hay algunos pasos para comenzar a utilizar el soporte de I18n en una aplicación de Rails.
2.1 Configurar el módulo I18n
Siguiendo la filosofía de "convención sobre configuración", Rails I18n proporciona cadenas de traducción predeterminadas razonables. Cuando se necesitan diferentes cadenas de traducción, se pueden anular.
Rails agrega todos los archivos .rb
y .yml
del directorio config/locales
a la ruta de carga de traducciones, automáticamente.
El archivo de configuración en.yml
predeterminado en este directorio contiene un par de cadenas de traducción de muestra:
en:
hello: "Hola mundo"
Esto significa que, en la configuración regional :en
, la clave hello se asignará a la cadena Hola mundo. Todas las cadenas dentro de Rails se internacionalizan de esta manera, consulte, por ejemplo, los mensajes de validación de Active Model en el archivo activemodel/lib/active_model/locale/en.yml
o los formatos de fecha y hora en el archivo activesupport/lib/active_support/locale/en.yml
. Puede utilizar YAML o Hashes estándar de Ruby para almacenar traducciones en el backend predeterminado (Simple).
La biblioteca I18n utilizará inglés como configuración regional predeterminada, es decir, si no se establece una configuración regional diferente, se utilizará :en
para buscar traducciones.
NOTA: La biblioteca i18n adopta un enfoque pragmático para las claves de configuración regional (después de alguna discusión), incluyendo solo la parte de "idioma" de la configuración regional, como :en
, :pl
, no la parte de "región", como :"en-US"
o :"en-GB"
, que se utilizan tradicionalmente para separar "idiomas" y "configuración regional" o "dialectos". Muchas aplicaciones internacionales utilizan solo el elemento "idioma" de una configuración regional, como :cs
, :th
o :es
(para checo, tailandés y español). Sin embargo, también existen diferencias regionales dentro de diferentes grupos de idiomas que pueden ser importantes. Por ejemplo, en la configuración regional :"en-US"
tendría $ como símbolo de moneda, mientras que en :"en-GB"
tendría £. Nada impide separar las configuraciones regionales y otras configuraciones de esta manera: solo tiene que proporcionar una configuración regional completa de "inglés - Reino Unido" en un diccionario :"en-GB"
.
La ruta de carga de traducciones (I18n.load_path
) es una matriz de rutas de archivos que se cargarán automáticamente. La configuración de esta ruta permite personalizar la estructura del directorio de traducciones y el esquema de nomenclatura de archivos.
NOTA: El backend carga estas traducciones de forma diferida cuando se busca una traducción por primera vez. Este backend se puede cambiar por otro incluso después de que las traducciones ya se hayan anunciado.
Puede cambiar la configuración regional predeterminada y configurar las rutas de carga de traducciones en config/application.rb
de la siguiente manera:
config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}')]
config.i18n.default_locale = :de
La ruta de carga debe especificarse antes de buscar cualquier traducción. Para cambiar la configuración regional predeterminada desde un inicializador en lugar de config/application.rb
:
# config/initializers/locale.rb
# Donde la biblioteca I18n debe buscar archivos de traducción
I18n.load_path += Dir[Rails.root.join('lib', 'locale', '*.{rb,yml}')]
# Configuración regional permitida disponible para la aplicación
I18n.available_locales = [:en, :pt]
# Establecer la configuración regional predeterminada en algo distinto de :en
I18n.default_locale = :pt
Tenga en cuenta que agregar directamente a I18n.load_path
en lugar de a la configuración de I18n de la aplicación no anulará las traducciones de gemas externas.
2.2 Administrar la configuración regional en todas las solicitudes
Es probable que una aplicación localizada necesite proporcionar soporte para varias configuraciones regionales. Para lograr esto, la configuración regional debe establecerse al comienzo de cada solicitud para que todas las cadenas se traduzcan utilizando la configuración regional deseada durante la vida útil de esa solicitud.
La configuración regional predeterminada se utiliza para todas las traducciones a menos que se utilice I18n.locale=
o I18n.with_locale
.
I18n.locale
puede filtrarse en solicitudes posteriores atendidas por el mismo hilo/proceso si no se establece de manera consistente en cada controlador. Por ejemplo, ejecutar I18n.locale = :es
en una solicitud POST tendrá efectos en todas las solicitudes posteriores a los controladores que no establezcan la configuración regional, pero solo en ese hilo/proceso en particular. Por esa razón, en lugar de I18n.locale =
se puede utilizar I18n.with_locale
, que no tiene este problema de filtración.
La configuración regional se puede establecer en un around_action
en el ApplicationController
:
around_action :switch_locale
def switch_locale(&action)
locale = params[:locale] || I18n.default_locale
I18n.with_locale(locale, &action)
end
Este ejemplo ilustra esto utilizando un parámetro de consulta de URL para establecer la configuración regional (por ejemplo, http://example.com/books?locale=pt
). Con este enfoque, http://localhost:3000?locale=pt
muestra la localización en portugués, mientras que http://localhost:3000?locale=de
carga una localización en alemán.
La configuración regional se puede establecer utilizando uno de muchos enfoques diferentes.
2.2.1 Establecer la configuración regional desde el nombre de dominio
Una opción que tiene es establecer la configuración regional a partir del nombre de dominio donde se ejecuta su aplicación. Por ejemplo, queremos que www.example.com
cargue la configuración regional en inglés (o predeterminada), y www.example.es
cargue la configuración regional en español. Por lo tanto, se utiliza el nombre de dominio de nivel superior para establecer la configuración regional. Esto tiene varias ventajas:
* La ubicación es una parte obvia de la URL.
* Las personas comprenden intuitivamente en qué idioma se mostrará el contenido.
* Es muy trivial de implementar en Rails.
* Los motores de búsqueda parecen gustar que el contenido en diferentes idiomas se encuentre en dominios diferentes e interconectados.
Puedes implementarlo de la siguiente manera en tu ApplicationController
:
around_action :switch_locale
def switch_locale(&action)
locale = extract_locale_from_tld || I18n.default_locale
I18n.with_locale(locale, &action)
end
# Obtén la ubicación del dominio de nivel superior o devuelve +nil+ si esa ubicación no está disponible
# Debes agregar algo como:
# 127.0.0.1 application.com
# 127.0.0.1 application.it
# 127.0.0.1 application.pl
# en tu archivo /etc/hosts para probar esto localmente
def extract_locale_from_tld
parsed_locale = request.host.split('.').last
I18n.available_locales.map(&:to_s).include?(parsed_locale) ? parsed_locale : nil
end
También podemos establecer la ubicación desde el subdominio de una manera muy similar:
# Obtén el código de ubicación del subdominio de la solicitud (como http://it.application.local:3000)
# Debes agregar algo como:
# 127.0.0.1 gr.application.local
# en tu archivo /etc/hosts para probar esto localmente
def extract_locale_from_subdomain
parsed_locale = request.subdomains.first
I18n.available_locales.map(&:to_s).include?(parsed_locale) ? parsed_locale : nil
end
Si tu aplicación incluye un menú de cambio de ubicación, tendrías algo como esto:
link_to("Deutsch", "#{APP_CONFIG[:deutsch_website_url]}#{request.env['PATH_INFO']}")
suponiendo que establezcas APP_CONFIG[:deutsch_website_url]
con algún valor como http://www.application.de
.
Esta solución tiene las ventajas mencionadas anteriormente, sin embargo, es posible que no puedas o no desees proporcionar diferentes localizaciones ("versiones de idioma") en diferentes dominios. La solución más obvia sería incluir el código de ubicación en los parámetros de la URL (o en la ruta de la solicitud).
2.2.2 Estableciendo la ubicación desde los parámetros de la URL
La forma más común de establecer (y pasar) la ubicación sería incluirla en los parámetros de la URL, como hicimos en el I18n.with_locale(params[:locale], &action)
around_action en el primer ejemplo. Nos gustaría tener URLs como www.example.com/books?locale=ja
o www.example.com/ja/books
en este caso.
Este enfoque tiene casi el mismo conjunto de ventajas que establecer la ubicación desde el nombre de dominio: es decir, es RESTful y está de acuerdo con el resto de la World Wide Web. Sin embargo, requiere un poco más de trabajo para implementarlo.
Obtener la ubicación de params
y establecerla en consecuencia no es difícil; sin embargo, incluirla en cada URL y, por lo tanto, pasarla a través de las solicitudes sí lo es. Sería tedioso y probablemente imposible incluir una opción explícita en cada URL, por ejemplo link_to(books_url(locale: I18n.locale))
.
Rails contiene infraestructura para "centralizar decisiones dinámicas sobre las URL" en su ApplicationController#default_url_options
, que es útil precisamente en este escenario: nos permite establecer "valores predeterminados" para url_for
y los métodos auxiliares dependientes de él (implementando/sobrescribiendo default_url_options
).
Podemos incluir algo como esto en nuestro ApplicationController
:
# app/controllers/application_controller.rb
def default_url_options
{ locale: I18n.locale }
end
Cada método auxiliar dependiente de url_for
(por ejemplo, los auxiliares para rutas con nombre como root_path
o root_url
, rutas de recursos como books_path
o books_url
, etc.) ahora incluirá automáticamente la ubicación en la cadena de consulta, como esto: http://localhost:3001/?locale=ja
.
Puede que estés satisfecho con esto. Sin embargo, afecta la legibilidad de las URL cuando la ubicación "cuelga" al final de cada URL en tu aplicación. Además, desde el punto de vista arquitectónico, la ubicación suele estar jerárquicamente por encima de las demás partes del dominio de la aplicación: y las URL deben reflejar esto.
Probablemente quieras que las URL se vean así: http://www.example.com/en/books
(que carga la ubicación en inglés) y http://www.example.com/nl/books
(que carga la ubicación en holandés). Esto se puede lograr con la estrategia de "sobrescribir default_url_options
" mencionada anteriormente: solo tienes que configurar tus rutas con scope
:
# config/routes.rb
scope "/:locale" do
resources :books
end
Ahora, cuando llames al método books_path
, deberías obtener "/en/books"
(para la ubicación predeterminada). Una URL como http://localhost:3001/nl/books
debería cargar la ubicación en holandés y, a continuación, las llamadas a books_path
deberían devolver "/nl/books"
(porque la ubicación cambió).
ADVERTENCIA. Dado que el valor de retorno de default_url_options
se almacena en caché por solicitud, las URL en un selector de ubicación no se pueden generar invocando a los auxiliares en un bucle que establece la I18n.locale
correspondiente en cada iteración. En su lugar, deja I18n.locale
sin cambios y pasa una opción explícita :locale
al auxiliar o edita request.original_fullpath
.
Si no deseas forzar el uso de una ubicación en tus rutas, puedes usar un ámbito de ruta opcional (indicado por los paréntesis) de la siguiente manera:
# config/routes.rb
scope "(:locale)", locale: /en|nl/ do
resources :books
end
Con este enfoque, no obtendrás un Routing Error
al acceder a tus recursos, como http://localhost:3001/books
, sin una configuración regional. Esto es útil cuando quieres usar la configuración regional predeterminada cuando no se especifica una.
Por supuesto, debes tener especial cuidado con la URL raíz (generalmente "homepage" o "dashboard") de tu aplicación. Una URL como http://localhost:3001/nl
no funcionará automáticamente, porque la declaración root to: "dashboard#index"
en tu archivo routes.rb
no tiene en cuenta la configuración regional. (Y con razón: solo hay una URL "root".)
Probablemente necesitarías mapear URLs como estas:
# config/routes.rb
get '/:locale' => 'dashboard#index'
Ten especial cuidado con el orden de tus rutas, para que esta declaración de ruta no "se coma" otras. (Es posible que desees agregarla directamente antes de la declaración root :to
).
NOTA: Echa un vistazo a varias gemas que simplifican el trabajo con rutas: routing_filter, route_translator.
2.2.3 Configuración de la configuración regional desde las preferencias del usuario
Una aplicación con usuarios autenticados puede permitir a los usuarios establecer una preferencia de configuración regional a través de la interfaz de la aplicación. Con este enfoque, la preferencia de configuración regional seleccionada por el usuario se guarda en la base de datos y se utiliza para establecer la configuración regional para las solicitudes autenticadas de ese usuario.
around_action :switch_locale
def switch_locale(&action)
locale = current_user.try(:locale) || I18n.default_locale
I18n.with_locale(locale, &action)
end
2.2.4 Elección de una configuración regional implícita
Cuando no se ha establecido una configuración regional explícita para una solicitud (por ejemplo, a través de uno de los métodos anteriores), una aplicación debe intentar inferir la configuración regional deseada.
2.2.4.1 Inferir la configuración regional desde la cabecera de idioma
La cabecera HTTP Accept-Language
indica el idioma preferido para la respuesta de la solicitud. Los navegadores establecen este valor de cabecera en función de la configuración de preferencia de idioma del usuario, por lo que es una buena opción para inferir una configuración regional.
Una implementación trivial de uso de una cabecera Accept-Language
sería:
def switch_locale(&action)
logger.debug "* Accept-Language: #{request.env['HTTP_ACCEPT_LANGUAGE']}"
locale = extract_locale_from_accept_language_header
logger.debug "* Locale set to '#{locale}'"
I18n.with_locale(locale, &action)
end
private
def extract_locale_from_accept_language_header
request.env['HTTP_ACCEPT_LANGUAGE'].scan(/^[a-z]{2}/).first
end
En la práctica, se necesita un código más robusto para hacer esto de manera confiable. La biblioteca http_accept_language de Iain Hecker o el middleware Rack locale de Ryan Tomayko proporcionan soluciones a este problema.
2.2.4.2 Inferir la configuración regional desde la geolocalización de IP
La dirección IP del cliente que realiza la solicitud se puede utilizar para inferir la región del cliente y, por lo tanto, su configuración regional. Se pueden utilizar servicios como GeoLite2 Country o gemas como geocoder para implementar este enfoque.
En general, este enfoque es mucho menos confiable que el uso de la cabecera de idioma y no se recomienda para la mayoría de las aplicaciones web.
2.2.5 Almacenar la configuración regional desde la sesión o las cookies
ADVERTENCIA: Puede que te tiente almacenar la configuración regional elegida en una sesión o una cookie. Sin embargo, no lo hagas. La configuración regional debe ser transparente y formar parte de la URL. De esta manera, no romperás las suposiciones básicas de las personas sobre la web misma: si envías una URL a un amigo, deberían ver la misma página y contenido que tú. Una palabra elegante para esto sería que estás siendo RESTful. Lee más sobre el enfoque RESTful en los artículos de Stefan Tilkov. A veces hay excepciones a esta regla y se discuten a continuación.
3 Internacionalización y Localización
¡OK! Ahora has inicializado el soporte de I18n para tu aplicación Ruby on Rails y le has indicado qué configuración regional usar y cómo conservarla entre las solicitudes.
A continuación, necesitamos internacionalizar nuestra aplicación mediante la abstracción de cada elemento específico de la configuración regional. Finalmente, necesitamos localizarla proporcionando las traducciones necesarias para estas abstracciones.
Dado el siguiente ejemplo:
# config/routes.rb
Rails.application.routes.draw do
root to: "home#index"
end
# app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
around_action :switch_locale
def switch_locale(&action)
locale = params[:locale] || I18n.default_locale
I18n.with_locale(locale, &action)
end
end
# app/controllers/home_controller.rb
class HomeController < ApplicationController
def index
flash[:notice] = "Hello Flash"
end
end
<!-- app/views/home/index.html.erb -->
<h1>Hello World</h1>
<p><%= flash[:notice] %></p>
3.1 Abstracción de código localizado
En nuestro código, hay dos cadenas escritas en inglés que se mostrarán en nuestra respuesta ("Hello Flash" y "Hello World"). Para internacionalizar este código, estas cadenas deben ser reemplazadas por llamadas al ayudante #t
de Rails con una clave adecuada para cada cadena:
# app/controllers/home_controller.rb
class HomeController < ApplicationController
def index
flash[:notice] = t(:hello_flash)
end
end
<!-- app/views/home/index.html.erb -->
<h1><%= t :hello_world %></h1>
<p><%= flash[:notice] %></p>
Ahora, cuando se renderiza esta vista, mostrará un mensaje de error que te indica que faltan las traducciones para las claves :hello_world
y :hello_flash
.
NOTA: Rails agrega un método auxiliar t
(translate
) a tus vistas para que no necesites escribir I18n.t
todo el tiempo. Además, este método auxiliar capturará las traducciones faltantes y envolverá el mensaje de error resultante en un <span class="translation_missing">
.
3.2 Proporcionar traducciones para cadenas internacionalizadas
Agrega las traducciones faltantes en los archivos de diccionario de traducción:
# config/locales/en.yml
en:
hello_world: ¡Hola mundo!
hello_flash: ¡Hola flash!
# config/locales/pirate.yml
pirate:
hello_world: ¡Ahoy Mundo!
hello_flash: ¡Ahoy Flash!
Como la default_locale
no ha cambiado, las traducciones utilizan la localización :en
y la respuesta muestra las cadenas en inglés:
Si la localización se establece a través de la URL en la localización pirata (http://localhost:3000?locale=pirate
), la respuesta muestra las cadenas piratas:
NOTA: Debes reiniciar el servidor cuando agregues nuevos archivos de localización.
Puedes utilizar archivos YAML (.yml
) o archivos Ruby simples (.rb
) para almacenar tus traducciones en SimpleStore. YAML es la opción preferida entre los desarrolladores de Rails. Sin embargo, tiene una gran desventaja. YAML es muy sensible a los espacios en blanco y a los caracteres especiales, por lo que la aplicación puede no cargar correctamente el diccionario. Los archivos Ruby harán que tu aplicación se bloquee en la primera solicitud, por lo que podrás encontrar fácilmente qué está mal. (Si encuentras algún problema "extraño" con los diccionarios YAML, intenta poner la parte relevante de tu diccionario en un archivo Ruby).
Si tus traducciones se almacenan en archivos YAML, ciertas claves deben escaparse. Estas son:
- true, on, yes
- false, off, no
Ejemplos:
# config/locales/en.yml
en:
success:
'true': '¡Verdadero!'
'on': '¡Encendido!'
'false': '¡Falso!'
failure:
true: '¡Verdadero!'
off: '¡Apagado!'
false: '¡Falso!'
I18n.t 'success.true' # => '¡Verdadero!'
I18n.t 'success.on' # => '¡Encendido!'
I18n.t 'success.false' # => '¡Falso!'
I18n.t 'failure.false' # => Traducción faltante
I18n.t 'failure.off' # => Traducción faltante
I18n.t 'failure.true' # => Traducción faltante
3.3 Pasar variables a las traducciones
Una consideración clave para internacionalizar correctamente una aplicación es evitar hacer suposiciones incorrectas sobre las reglas gramaticales al abstraer el código localizado. Las reglas gramaticales que parecen fundamentales en una localización pueden no ser válidas en otra.
La abstracción incorrecta se muestra en el siguiente ejemplo, donde se hacen suposiciones sobre el orden de las diferentes partes de la traducción. Ten en cuenta que Rails proporciona un método auxiliar number_to_currency
para manejar el siguiente caso.
<!-- app/views/products/show.html.erb -->
<%= "#{t('currency')}#{@product.price}" %>
# config/locales/en.yml
en:
currency: "$"
# config/locales/es.yml
es:
currency: "€"
Si el precio del producto es 10, entonces la traducción correcta para español es "10 €" en lugar de "€10", pero la abstracción no puede proporcionarla.
Para crear una abstracción correcta, la gema I18n incluye una función llamada interpolación de variables que te permite usar variables en las definiciones de traducción y pasar los valores de estas variables al método de traducción.
La abstracción correcta se muestra en el siguiente ejemplo:
<!-- app/views/products/show.html.erb -->
<%= t('product_price', price: @product.price) %>
# config/locales/en.yml
en:
product_price: "$%{price}"
# config/locales/es.yml
es:
product_price: "%{price} €"
Todas las decisiones gramaticales y de puntuación se toman en la definición misma, por lo que la abstracción puede proporcionar una traducción correcta.
NOTA: Las palabras clave default
y scope
están reservadas y no se pueden usar como nombres de variables. Si se utilizan, se generará una excepción I18n::ReservedInterpolationKey
. Si una traducción espera una variable de interpolación, pero esta no se ha pasado a #translate
, se generará una excepción I18n::MissingInterpolationArgument
.
3.4 Agregar formatos de fecha/hora
¡OK! Ahora agreguemos una marca de tiempo a la vista, para poder demostrar también la función de localización de fecha/hora. Para localizar el formato de hora, se pasa el objeto Time a I18n.l
o (preferiblemente) se utiliza el método #l
de Rails. Puedes elegir un formato pasando la opción :format
- por defecto se utiliza el formato :default
.
<!-- app/views/home/index.html.erb -->
<h1><%= t :hello_world %></h1>
<p><%= flash[:notice] %></p>
<p><%= l Time.now, format: :short %></p>
Y en nuestro archivo de traducciones piratas agreguemos un formato de hora (que ya está en los valores predeterminados de Rails para inglés):
# config/locales/pirate.yml
pirate:
time:
formats:
short: "arrrround %H'ish"
Entonces, eso te daría:
CONSEJO: En este momento es posible que necesites agregar algunos formatos de fecha/hora más para que el backend de I18n funcione como se espera (al menos para la localización 'pirate'). Por supuesto, existe una gran posibilidad de que alguien ya haya hecho todo el trabajo al traducir los valores predeterminados de Rails para tu localización. Consulta el repositorio rails-i18n en GitHub para obtener un archivo de varias localizaciones. Cuando coloques dicho archivo(s) en el directorio config/locales/
, estarán automáticamente listos para usar.
3.5 Reglas de inflexión para otros locales
Rails te permite definir reglas de inflexión (como reglas para singularización y pluralización) para locales distintos al inglés. En config/initializers/inflections.rb
, puedes definir estas reglas para varios locales. El inicializador contiene un ejemplo predeterminado para especificar reglas adicionales para el inglés; sigue ese formato para otros locales según consideres necesario.
3.6 Vistas localizadas
Supongamos que tienes un controlador de libros (BooksController) en tu aplicación. Tu acción index muestra contenido en la plantilla app/views/books/index.html.erb
. Cuando colocas una variante localizada de esta plantilla: index.es.html.erb
en el mismo directorio, Rails mostrará el contenido de esta plantilla cuando el idioma esté configurado en :es
. Cuando el idioma esté configurado en el idioma predeterminado, se utilizará la vista genérica index.html.erb
. (Versiones futuras de Rails podrían llevar esta localización automágica a los activos en public
, etc.)
Puedes aprovechar esta característica, por ejemplo, cuando trabajas con una gran cantidad de contenido estático que sería incómodo de colocar dentro de diccionarios YAML o Ruby. Sin embargo, ten en cuenta que cualquier cambio que desees hacer más adelante en la plantilla debe propagarse a todas ellas.
3.7 Organización de archivos de idioma
Cuando utilizas el almacenamiento SimpleStore predeterminado que se incluye con la biblioteca i18n, los diccionarios se almacenan en archivos de texto sin formato en el disco. Colocar las traducciones de todas las partes de tu aplicación en un archivo por idioma podría ser difícil de gestionar. Puedes almacenar estos archivos en una jerarquía que tenga sentido para ti.
Por ejemplo, tu directorio config/locales
podría verse así:
|-defaults
|---es.yml
|---en.yml
|-models
|---book
|-----es.yml
|-----en.yml
|-views
|---defaults
|-----es.yml
|-----en.yml
|---books
|-----es.yml
|-----en.yml
|---users
|-----es.yml
|-----en.yml
|---navigation
|-----es.yml
|-----en.yml
De esta manera, puedes separar los nombres de los modelos y atributos de los textos dentro de las vistas, y todo esto de los "valores predeterminados" (por ejemplo, formatos de fecha y hora). Otros almacenes para la biblioteca i18n podrían proporcionar diferentes formas de separación.
NOTA: El mecanismo de carga de idioma predeterminado en Rails no carga archivos de idioma en diccionarios anidados, como los que tenemos aquí. Por lo tanto, para que esto funcione, debemos indicar explícitamente a Rails que busque más allá:
# config/application.rb
config.i18n.load_path += Dir[Rails.root.join('config', 'locales', '**', '*.{rb,yml}')]
4 Resumen de las características de la API de I18n
Deberías tener un buen entendimiento de cómo usar la biblioteca i18n ahora y saber cómo internacionalizar una aplicación básica de Rails. En los siguientes capítulos, cubriremos sus características con más detalle.
Estos capítulos mostrarán ejemplos utilizando tanto el método I18n.translate
como el método auxiliar de vista translate
(teniendo en cuenta las características adicionales proporcionadas por el método auxiliar de vista).
Se cubrirán características como estas:
- búsqueda de traducciones
- interpolación de datos en las traducciones
- pluralización de traducciones
- uso de traducciones HTML seguras (solo en el método auxiliar de vista)
- localización de fechas, números, moneda, etc.
4.1 Búsqueda de traducciones
4.1.1 Búsqueda básica, ámbitos y claves anidadas
Las traducciones se buscan por claves que pueden ser tanto símbolos como cadenas, por lo que estas llamadas son equivalentes:
I18n.t :message
I18n.t 'message'
El método translate
también acepta una opción :scope
que puede contener una o más claves adicionales que se utilizarán para especificar un "espacio de nombres" o ámbito para una clave de traducción:
I18n.t :record_invalid, scope: [:activerecord, :errors, :messages]
Esto busca el mensaje :record_invalid
en los mensajes de error de Active Record.
Además, tanto la clave como los ámbitos se pueden especificar como claves separadas por puntos, como en:
I18n.translate "activerecord.errors.messages.record_invalid"
Por lo tanto, las siguientes llamadas son equivalentes:
I18n.t 'activerecord.errors.messages.record_invalid'
I18n.t 'errors.messages.record_invalid', scope: :activerecord
I18n.t :record_invalid, scope: 'activerecord.errors.messages'
I18n.t :record_invalid, scope: [:activerecord, :errors, :messages]
4.1.2 Valores predeterminados
Cuando se proporciona una opción :default
, su valor se devolverá si la traducción no existe:
I18n.t :missing, default: 'No está aquí'
# => 'No está aquí'
Si el valor :default
es un símbolo, se utilizará como clave y se traducirá. Se pueden proporcionar varios valores como predeterminados. Se devolverá el primer valor que dé como resultado un valor.
Por ejemplo, lo siguiente primero intenta traducir la clave :missing
y luego la clave :also_missing
. Como ambas no producen un resultado, se devolverá la cadena "No está aquí":
I18n.t :missing, default: [:also_missing, 'No está aquí']
# => 'No está aquí'
4.1.3 Búsqueda a granel y en espacios de nombres
Para buscar varias traducciones a la vez, se puede pasar un array de claves: ```ruby I18n.t [:odd, :even], scope: 'errors.messages'
=> ["debe ser impar", "debe ser par"]
Además, una clave puede traducirse a un hash (potencialmente anidado) de traducciones agrupadas. Por ejemplo, se puede recibir _todos_ los mensajes de error de Active Record como un Hash con:
```ruby
I18n.t 'errors.messages'
# => {:inclusion=>"no está incluido en la lista", :exclusion=> ... }
Si desea realizar interpolación en un hash masivo de traducciones, debe pasar deep_interpolation: true
como parámetro. Cuando tiene el siguiente diccionario:
en:
welcome:
title: "¡Bienvenido!"
content: "Bienvenido a %{app_name}"
entonces la interpolación anidada se ignorará sin la configuración:
I18n.t 'welcome', app_name: 'librería'
# => {:title=>"¡Bienvenido!", :content=>"Bienvenido a %{app_name}"}
I18n.t 'welcome', deep_interpolation: true, app_name: 'librería'
# => {:title=>"¡Bienvenido!", :content=>"Bienvenido a la librería"}
4.1.4 Búsqueda "Lazy"
Rails implementa una forma conveniente de buscar la configuración regional dentro de vistas. Cuando tiene el siguiente diccionario:
es:
books:
index:
title: "Título"
puede buscar el valor de books.index.title
dentro de la plantilla app/views/books/index.html.erb
de la siguiente manera (observe el punto):
<%= t '.title' %>
NOTA: La búsqueda automática de configuración regional por parcial solo está disponible desde el método auxiliar de vista translate
.
La búsqueda "Lazy" también se puede usar en controladores:
en:
books:
create:
success: ¡Libro creado!
Esto es útil para establecer mensajes flash, por ejemplo:
class BooksController < ApplicationController
def create
# ...
redirect_to books_url, notice: t('.success')
end
end
4.2 Pluralización
En muchos idiomas, incluido el inglés, solo hay dos formas, singular y plural, para una cadena dada, por ejemplo, "1 mensaje" y "2 mensajes". Otros idiomas (Árabe, Japonés, Ruso y muchos más) tienen diferentes gramáticas que tienen formas plurales adicionales o menos formas plurales. Por lo tanto, la API de I18n proporciona una función de pluralización flexible.
La variable de interpolación :count
tiene un papel especial en que tanto se interpola en la traducción como se utiliza para seleccionar una pluralización de las traducciones según las reglas de pluralización definidas en el backend de pluralización. Por defecto, solo se aplican las reglas de pluralización en inglés.
I18n.backend.store_translations :en, inbox: {
zero: 'sin mensajes', # opcional
one: 'un mensaje',
other: '%{count} mensajes'
}
I18n.translate :inbox, count: 2
# => '2 mensajes'
I18n.translate :inbox, count: 1
# => 'un mensaje'
I18n.translate :inbox, count: 0
# => 'sin mensajes'
El algoritmo para la pluralización en :en
es tan simple como:
lookup_key = :zero if count == 0 && entry.has_key?(:zero)
lookup_key ||= count == 1 ? :one : :other
entry[lookup_key]
La traducción denominada :one
se considera singular y se utiliza :other
como plural. Si el recuento es cero y hay una entrada :zero
, entonces se utilizará en lugar de :other
.
Si la búsqueda de la clave no devuelve un Hash adecuado para la pluralización, se genera una excepción I18n::InvalidPluralizationData
.
4.2.1 Reglas específicas de la configuración regional
La gema I18n proporciona un backend de pluralización que se puede utilizar para habilitar reglas específicas de la configuración regional. Inclúyalo en el backend Simple y luego agregue los algoritmos de pluralización localizados al almacén de traducción, como i18n.plural.rule
.
I18n::Backend::Simple.include(I18n::Backend::Pluralization)
I18n.backend.store_translations :pt, i18n: { plural: { rule: lambda { |n| [0, 1].include?(n) ? :one : :other } } }
I18n.backend.store_translations :pt, apples: { one: 'uno o ninguno', other: 'más de uno' }
I18n.t :apples, count: 0, locale: :pt
# => 'uno o ninguno'
Alternativamente, se puede utilizar la gema separada rails-i18n para proporcionar un conjunto más completo de reglas de pluralización específicas de la configuración regional.
4.3 Establecer y pasar una configuración regional
La configuración regional se puede establecer de forma pseudo-global en I18n.locale
(que utiliza Thread.current
de la misma manera que, por ejemplo, Time.zone
) o se puede pasar como una opción a #translate
y #localize
.
Si no se pasa ninguna configuración regional, se utiliza I18n.locale
:
I18n.locale = :de
I18n.t :foo
I18n.l Time.now
Pasando explícitamente una configuración regional:
I18n.t :foo, locale: :de
I18n.l Time.now, locale: :de
I18n.locale
se establece de forma predeterminada en I18n.default_locale
, que se establece de forma predeterminada en :en
. La configuración regional predeterminada se puede establecer de la siguiente manera:
I18n.default_locale = :de
4.4 Usar traducciones HTML seguras
Las claves con un sufijo '_html' y las claves llamadas 'html' se marcan como seguras en HTML. Cuando las usa en vistas, el HTML no se escapará.
# config/locales/en.yml
en:
welcome: <b>bienvenido!</b>
hello_html: <b>¡hola!</b>
title:
html: <b>¡título!</b>
<!-- app/views/home/index.html.erb -->
<div><%= t('welcome') %></div>
<div><%= raw t('welcome') %></div>
<div><%= t('hello_html') %></div>
<div><%= t('title.html') %></div>
La interpolación se escapa según sea necesario. Por ejemplo, dado:
en:
welcome_html: "<b>Bienvenido %{username}!</b>"
puedes pasar de forma segura el nombre de usuario establecido por el usuario:
<%# Esto es seguro, se escapará si es necesario. %>
<%= t('welcome_html', username: @current_user.username) %>
Las cadenas seguras, por otro lado, se interpolan literalmente.
NOTA: La conversión automática a texto de traducción seguro en HTML solo está disponible desde el método de ayuda translate
(o t
). Esto funciona en vistas y controladores.
4.5 Traducciones para modelos de Active Record
Puedes utilizar los métodos Model.model_name.human
y Model.human_attribute_name(attribute)
para buscar de forma transparente las traducciones para los nombres de tu modelo y atributos.
Por ejemplo, cuando agregas las siguientes traducciones:
en:
activerecord:
models:
user: Cliente
attributes:
user:
login: "Nombre de usuario"
# traducirá el atributo "login" del modelo User como "Nombre de usuario"
Entonces User.model_name.human
devolverá "Cliente" y User.human_attribute_name("login")
devolverá "Nombre de usuario".
También puedes establecer una forma plural para los nombres de los modelos, agregando lo siguiente:
en:
activerecord:
models:
user:
one: Cliente
other: Clientes
Entonces User.model_name.human(count: 2)
devolverá "Clientes". Con count: 1
o sin parámetros devolverá "Cliente".
En caso de que necesites acceder a atributos anidados dentro de un modelo dado, debes anidarlos bajo modelo/atributo
en el nivel del modelo de tu archivo de traducción:
en:
activerecord:
attributes:
user/role:
admin: "Administrador"
contributor: "Contribuyente"
Entonces User.human_attribute_name("role.admin")
devolverá "Administrador".
NOTA: Si estás utilizando una clase que incluye ActiveModel
y no hereda de ActiveRecord::Base
, reemplaza activerecord
por activemodel
en las rutas de clave anteriores.
4.5.1 Alcance de los mensajes de error
Los mensajes de error de validación de Active Record también se pueden traducir fácilmente. Active Record te proporciona un par de espacios de nombres donde puedes colocar tus traducciones de mensajes para proporcionar mensajes y traducciones diferentes para ciertos modelos, atributos y/o validaciones. También tiene en cuenta la herencia de una sola tabla de forma transparente.
Esto te brinda medios bastante poderosos para ajustar de manera flexible tus mensajes a las necesidades de tu aplicación.
Considera un modelo User con una validación para el atributo name de esta manera:
class User < ApplicationRecord
validates :name, presence: true
end
La clave para el mensaje de error en este caso es :blank
. Active Record buscará esta clave en los espacios de nombres:
activerecord.errors.models.[nombre_del_modelo].attributes.[nombre_del_atributo]
activerecord.errors.models.[nombre_del_modelo]
activerecord.errors.messages
errors.attributes.[nombre_del_atributo]
errors.messages
Por lo tanto, en nuestro ejemplo, intentará las siguientes claves en este orden y devolverá el primer resultado:
activerecord.errors.models.user.attributes.name.blank
activerecord.errors.models.user.blank
activerecord.errors.messages.blank
errors.attributes.name.blank
errors.messages.blank
Cuando tus modelos también utilizan herencia, los mensajes se buscan en la cadena de herencia.
Por ejemplo, podrías tener un modelo Admin que hereda de User:
class Admin < User
validates :name, presence: true
end
Entonces Active Record buscará los mensajes en este orden:
activerecord.errors.models.admin.attributes.name.blank
activerecord.errors.models.admin.blank
activerecord.errors.models.user.attributes.name.blank
activerecord.errors.models.user.blank
activerecord.errors.messages.blank
errors.attributes.name.blank
errors.messages.blank
De esta manera, puedes proporcionar traducciones especiales para varios mensajes de error en diferentes puntos de la cadena de herencia de tu modelo y en los ámbitos de atributos, modelos o predeterminados.
4.5.2 Interpolación de mensajes de error
El nombre del modelo traducido, el nombre del atributo traducido y el valor siempre están disponibles para la interpolación como model
, attribute
y value
, respectivamente.
Entonces, por ejemplo, en lugar del mensaje de error predeterminado "no puede estar en blanco"
, podrías usar el nombre del atributo de esta manera: "Por favor, completa tu %{attribute}"
.
count
, cuando está disponible, se puede utilizar para la pluralización si está presente:
validación | con opción | mensaje | interpolación |
---|---|---|---|
confirmation | - | :confirmation | attribute |
acceptance | - | :accepted | - |
presence | - | :blank | - |
absence | - | :present | - |
length | :within, :in | :too_short | count |
length | :within, :in | :too_long | count |
length | :is | :wrong_length | count |
length | :minimum | :too_short | count |
length | :maximum | :too_long | count |
uniqueness | - | :taken | - |
format | - | :invalid | - |
inclusion | - | :inclusion | - |
exclusion | - | :exclusion | - |
associated | - | :invalid | - |
non-optional association | - | :required | - |
numericality | - | :not_a_number | - |
numericality | :greater_than | :greater_than | count |
numericality | :greater_than_or_equal_to | :greater_than_or_equal_to | count |
numericality | :equal_to | :equal_to | count |
numericality | :less_than | :less_than | count |
numericality | :less_than_or_equal_to | :less_than_or_equal_to | count |
numericality | :other_than | :other_than | count |
numericality | :only_integer | :not_an_integer | - |
numericality | :in | :in | count |
numericality | :odd | :odd | - |
numericality | :even | :even | - |
comparison | :greater_than | :greater_than | count |
comparison | :greater_than_or_equal_to | :greater_than_or_equal_to | count |
comparison | :equal_to | :equal_to | count |
comparison | :less_than | :less_than | count |
comparison | :less_than_or_equal_to | :less_than_or_equal_to | count |
comparison | :other_than | :other_than | count |
4.6 Traducciones para los Asuntos de Correo Electrónico de Action Mailer
Si no pasas un asunto al método mail
, Action Mailer intentará encontrarlo en tus traducciones. La búsqueda se realizará utilizando el patrón <mailer_scope>.<action_name>.subject
para construir la clave.
# user_mailer.rb
class UserMailer < ActionMailer::Base
def welcome(user)
#...
end
end
en:
user_mailer:
welcome:
subject: "¡Bienvenido a Rails Guides!"
Para enviar parámetros a la interpolación, utiliza el método default_i18n_subject
en el mailer.
# user_mailer.rb
class UserMailer < ActionMailer::Base
def welcome(user)
mail(to: user.email, subject: default_i18n_subject(user: user.name))
end
end
en:
user_mailer:
welcome:
subject: "%{user}, ¡bienvenido a Rails Guides!"
4.7 Resumen de Otros Métodos Incorporados que Proporcionan Soporte de I18n
Rails utiliza cadenas fijas y otras localizaciones, como cadenas de formato y otra información de formato en un par de helpers. Aquí tienes un breve resumen.
4.7.1 Métodos de Ayuda de Action View
distance_of_time_in_words
traduce y pluraliza su resultado e interpola el número de segundos, minutos, horas, etc. Consulta las traducciones en datetime.distance_in_words.datetime_select
yselect_month
utilizan nombres de meses traducidos para poblar la etiqueta select resultante. Consulta date.month_names para las traducciones.datetime_select
también busca la opción de orden en date.order (a menos que pases la opción explícitamente). Todos los helpers de selección de fechas traducen el texto de ayuda utilizando las traducciones en el ámbito datetime.prompts si corresponde.Los helpers
number_to_currency
,number_with_precision
,number_to_percentage
,number_with_delimiter
ynumber_to_human_size
utilizan la configuración de formato de número ubicada en el ámbito number.
4.7.2 Métodos de Active Model
model_name.human
yhuman_attribute_name
utilizan traducciones para los nombres de modelo y los nombres de atributos si están disponibles en el ámbito activerecord.models. También admiten traducciones para nombres de clases heredadas (por ejemplo, para su uso con STI), como se explica anteriormente en "Ámbitos de mensajes de error".ActiveModel::Errors#generate_message
(que se utiliza en las validaciones de Active Model pero también se puede utilizar manualmente) utilizamodel_name.human
yhuman_attribute_name
(consultar arriba). También traduce el mensaje de error y admite traducciones para nombres de clases heredadas, como se explica anteriormente en "Ámbitos de mensajes de error".ActiveModel::Error#full_message
yActiveModel::Errors#full_messages
anteponen el nombre del atributo al mensaje de error utilizando un formato buscado enerrors.format
(por defecto:"%{attribute} %{message}"
). Para personalizar el formato predeterminado, sobrescríbelo en los archivos de localización de la aplicación. Para personalizar el formato por modelo o por atributo, consultaconfig.active_model.i18n_customize_full_message
.
4.7.3 Métodos de Active Support
Array#to_sentence
utiliza la configuración de formato según se indica en el ámbito support.array.
5 Cómo almacenar tus traducciones personalizadas
El backend Simple que se incluye con Active Support te permite almacenar traducciones tanto en formato Ruby simple como en formato YAML.2
Por ejemplo, un Hash de Ruby que proporciona traducciones puede verse así:
{
pt: {
foo: {
bar: "baz"
}
}
}
El archivo YAML equivalente se vería así:
pt:
foo:
bar: baz
Como puedes ver, en ambos casos la clave de nivel superior es la localización. :foo
es una clave de espacio de nombres y :bar
es la clave para la traducción "baz".
Aquí tienes un ejemplo "real" del archivo de traducciones YAML en.yml
de Active Support:
en:
date:
formats:
default: "%Y-%m-%d"
short: "%b %d"
long: "%B %d, %Y"
Por lo tanto, todas las siguientes búsquedas equivalentes devolverán el formato de fecha :short
"%b %d"
:
I18n.t 'date.formats.short'
I18n.t 'formats.short', scope: :date
I18n.t :short, scope: 'date.formats'
I18n.t :short, scope: [:date, :formats]
En general, recomendamos utilizar YAML como formato para almacenar traducciones. Sin embargo, hay casos en los que quieres almacenar lambdas de Ruby como parte de tus datos de localización, por ejemplo, para formatos de fecha especiales.
6 Personaliza tu configuración de I18n
6.1 Uso de Diferentes Backends
Por varias razones, el backend Simple que se incluye con Active Support solo hace "lo más simple que podría funcionar" para Ruby on Rails3 ... lo que significa que solo se garantiza que funcione para el inglés y, como efecto secundario, para los idiomas que son muy similares al inglés. Además, el backend simple solo es capaz de leer traducciones pero no puede almacenarlas dinámicamente en ningún formato.
Eso no significa que estés limitado a estas restricciones. La gema Ruby I18n facilita mucho el intercambio de la implementación del backend Simple por algo que se ajuste mejor a tus necesidades, pasando una instancia de backend al setter I18n.backend=
.
Por ejemplo, puedes reemplazar el backend Simple con el backend Chain para encadenar varios backends juntos. Esto es útil cuando quieres utilizar traducciones estándar con un backend Simple pero almacenar traducciones personalizadas de la aplicación en una base de datos u otros backends. Con el backend Chain, podrías usar el backend Active Record y luego volver al backend Simple (por defecto):
I18n.backend = I18n::Backend::Chain.new(I18n::Backend::ActiveRecord.new, I18n.backend)
6.2 Uso de diferentes manejadores de excepciones
La API de I18n define las siguientes excepciones que se generarán por los backends cuando ocurran las condiciones inesperadas correspondientes:
Excepción | Razón |
---|---|
I18n::MissingTranslationData |
no se encontró una traducción para la clave solicitada |
I18n::InvalidLocale |
la configuración de I18n.locale no es válida (por ejemplo, nil ) |
I18n::InvalidPluralizationData |
se pasó una opción de conteo pero los datos de traducción no son adecuados para la pluralización |
I18n::MissingInterpolationArgument |
la traducción espera un argumento de interpolación que no se ha pasado |
I18n::ReservedInterpolationKey |
la traducción contiene un nombre de variable de interpolación reservada (es decir, uno de: scope , default ) |
I18n::UnknownFileType |
el backend no sabe cómo manejar un tipo de archivo que se agregó a I18n.load_path |
6.2.1 Personalizando cómo se maneja I18n::MissingTranslationData
Si config.i18n.raise_on_missing_translations
es true
, se generarán errores de I18n::MissingTranslationData
. Es una buena idea activar esto en tu entorno de prueba para poder detectar los lugares donde se solicitan traducciones faltantes.
Si config.i18n.raise_on_missing_translations
es false
(el valor predeterminado en todos los entornos), se imprimirá el mensaje de error de la excepción. Esto contiene la clave/scope faltante para que puedas corregir tu código.
Si deseas personalizar aún más este comportamiento, debes establecer config.i18n.raise_on_missing_translations = false
y luego implementar un I18n.exception_handler
. El manejador de excepciones personalizado puede ser un proc o una clase con un método call
:
# config/initializers/i18n.rb
module I18n
class RaiseExceptForSpecificKeyExceptionHandler
def call(exception, locale, key, options)
if key == "special.key"
"¡traducción faltante!" # devolver esto, no generarlo
elsif exception.is_a?(MissingTranslation)
raise exception.to_exception
else
raise exception
end
end
end
end
I18n.exception_handler = I18n::RaiseExceptForSpecificKeyExceptionHandler.new
Esto generaría todas las excepciones de la misma manera que lo haría el manejador predeterminado, excepto en el caso de I18n.t("special.key")
.
7 Traduciendo el contenido del modelo
La API de I18n descrita en esta guía está principalmente destinada a traducir cadenas de interfaz. Si deseas traducir el contenido del modelo (por ejemplo, publicaciones de blog), necesitarás una solución diferente para ayudarte con esto.
Varios gemas pueden ayudarte con esto:
- Mobility: Proporciona soporte para almacenar traducciones en muchos formatos, incluyendo tablas de traducción, columnas JSON (PostgreSQL), etc.
- Traco: Columnas traducibles almacenadas en la propia tabla del modelo
8 Conclusión
En este punto, deberías tener una buena visión general de cómo funciona el soporte de I18n en Ruby on Rails y estar listo para comenzar a traducir tu proyecto.
9 Contribuir a Rails I18n
El soporte de I18n en Ruby on Rails se introdujo en la versión 2.2 y aún está evolucionando. El proyecto sigue la buena tradición de desarrollo de Ruby on Rails de evolucionar soluciones en gemas y aplicaciones reales primero, y luego seleccionar las mejores características más útiles para su inclusión en el núcleo.
Por lo tanto, animamos a todos a experimentar con nuevas ideas y características en gemas u otras bibliotecas y hacerlas disponibles para la comunidad. (¡No olvides anunciar tu trabajo en nuestra lista de correo!)
Si encuentras que tu propio idioma no está incluido en nuestro repositorio de ejemplos de traducciones para Ruby on Rails, por favor fork el repositorio, agrega tus datos y envía una solicitud de extracción.
10 Recursos
- Grupo de Google: rails-i18n - Lista de correo del proyecto.
- GitHub: rails-i18n - Repositorio de código y rastreador de problemas para el proyecto rails-i18n. Lo más importante es que puedes encontrar muchos ejemplos de traducciones para Rails que deberían funcionar para tu aplicación en la mayoría de los casos.
- GitHub: i18n - Repositorio de código y rastreador de problemas para la gema i18n.
11 Autores
- Sven Fuchs (autor inicial)
- Karel Minařík
12 Notas al pie
1 O, para citar a Wikipedia: "La internacionalización es el proceso de diseñar una aplicación de software para que pueda adaptarse a varios idiomas y regiones sin cambios de ingeniería. La localización es el proceso de adaptar el software a una región o idioma específico mediante la adición de componentes específicos de la configuración regional y la traducción de texto".
2 Otros backends pueden permitir o requerir el uso de otros formatos, por ejemplo, un backend GetText puede permitir leer archivos GetText.
3 Una de estas razones es que no queremos implicar ninguna carga innecesaria para las aplicaciones que no necesitan capacidades de I18n, por lo que necesitamos mantener la biblioteca de I18n lo más simple posible para el inglés. Otra razón es que es prácticamente imposible implementar una solución única para todos los problemas relacionados con I18n para todos los idiomas existentes. Por lo tanto, de todos modos, una solución que nos permita intercambiar fácilmente toda la implementación es apropiada. Esto también facilita mucho experimentar con características y extensiones personalizadas.
Comentarios
Se te anima a ayudar a mejorar la calidad de esta guía.
Por favor, contribuye si encuentras algún error tipográfico o factual. Para empezar, puedes leer nuestra contribución a la documentación sección.
También puedes encontrar contenido incompleto o desactualizado. Por favor, añade cualquier documentación faltante para main. Asegúrate de revisar Edge Guides primero para verificar si los problemas ya están resueltos o no en la rama principal. Consulta las Directrices de las Guías de Ruby on Rails para el estilo y las convenciones.
Si por alguna razón encuentras algo que corregir pero no puedes solucionarlo tú mismo, por favor abre un problema.
Y por último, cualquier tipo de discusión sobre la documentación de Ruby on Rails es muy bienvenida en el Foro oficial de Ruby on Rails.