Ruby on Rails
I18n - Internacionalización
Buscar..
Sintaxis
- I18n.t ("clave")
- I18n.translate ("clave") # equivalente a
I18n.t("key")
- I18n.t ("clave", cuenta: 4)
- I18n.t ("key", param1: "Something", param2: "Else")
- I18n.t ("doesnt_exist", predeterminado: "clave") # especifique un valor predeterminado si falta la clave
- I18n.locale # =>: en
- I18n.locale =: en
- I18n.default_locale # =>: en
- I18n.default_locale =: en
- t (". clave") # igual que
I18n.t("key")
, pero con el alcance de la acción / plantilla desde la que se llama
Usa I18n en vistas
Suponiendo que tiene este archivo de configuración regional YAML:
# config/locales/en.yml
en:
header:
title: "My header title"
y desea mostrar su cadena de título, puede hacer esto
# in ERB files
<%= t('header.title') %>
# in SLIM files
= t('header.title')
I18n con argumentos
Puede pasar parámetros al método I18n t
:
# Example config/locales/en.yml
en:
page:
users: "%{users_count} users currently online"
# In models, controller, etc...
I18n.t('page.users', users_count: 12)
# In views
# ERB
<%= t('page.users', users_count: 12) %>
#SLIM
= t('page.users', users_count: 12)
# Shortcut in views - DRY!
# Use only the dot notation
# Important: Consider you have the following controller and view page#users
# ERB Example app/views/page/users.html.erb
<%= t('.users', users_count: 12) %>
Y consigue la siguiente salida:
"12 users currently online"
Pluralización
Puedes dejar que I18n maneje la pluralización por ti, solo usa el argumento count
.
Necesitas configurar tu archivo de configuración regional de esta manera:
# config/locales/en.yml
en:
online_users:
one: "1 user is online"
other: "%{count} users are online"
Y luego use la clave que acaba de crear pasando el argumento de count
a I18n.t
helper:
I18n.t("online_users", count: 1)
#=> "1 user is online"
I18n.t("online_users", count: 4)
#=> "4 users are online"
Establecer la configuración regional a través de solicitudes
En la mayoría de los casos, es posible que desee establecer la I18n
regional I18n
. Es posible que desee establecer la configuración regional para la sesión actual, el usuario actual o en función de un parámetro de URL. Esto se puede lograr fácilmente implementando una before_action
en uno de sus controladores, o en ApplicationController
para tenerlo en todos sus controladores.
class ApplicationController < ActionController::Base
before_action :set_locale
protected
def set_locale
# Remove inappropriate/unnecessary ones
I18n.locale = params[:locale] || # Request parameter
session[:locale] || # Current session
(current_user.preferred_locale if user_signed_in?) || # Model saved configuration
extract_locale_from_accept_language_header || # Language header - browser config
I18n.default_locale # Set in your config files, english by super-default
end
# Extract language from request header
def extract_locale_from_accept_language_header
if request.env['HTTP_ACCEPT_LANGUAGE']
lg = request.env['HTTP_ACCEPT_LANGUAGE'].scan(/^[a-z]{2}/).first.to_sym
lg.in?([:en, YOUR_AVAILABLE_LANGUAGES]) ? lg : nil
end
end
Basado en URL
El parámetro locale
podría provenir de una URL como esta
http://yourapplication.com/products?locale=en
O
http://yourapplication.com/en/products
Para lograr esto último, necesita editar sus routes
, agregando un scope
:
# config/routes.rb
scope "(:locale)", locale: /en|fr/ do
resources :products
end
Al hacer esto, visitar http://yourapplication.com/en/products
establecerá su configuración regional en :en
. En su lugar, visitar http://yourapplication.com/fr/products
lo configurará en :fr
. Además, no obtendrá un error de enrutamiento cuando falte el parámetro :locale
, ya que al visitar http://yourapplication.com/products
se cargará la configuración regional predeterminada I18n .
Sesión basada o basada en la persistencia
Esto supone que el usuario puede hacer clic en un botón / marca de idioma para cambiar el idioma. La acción puede dirigirse a un controlador que establece la sesión en el idioma actual (y eventualmente persistir los cambios en una base de datos si el usuario está conectado)
class SetLanguageController < ApplicationController
skip_before_filter :authenticate_user!
after_action :set_preferred_locale
# Generic version to handle a large list of languages
def change_locale
I18n.locale = sanitize_language_param
set_session_and_redirect
end
Debe definir sanitize_language_param con su lista de idiomas disponibles y, finalmente, manejar los errores en caso de que el idioma no exista.
Si tiene muy pocos idiomas, puede valer la pena definirlos así:
def fr
I18n.locale = :fr
set_session_and_redirect
end
def en
I18n.locale = :en
set_session_and_redirect
end
private
def set_session_and_redirect
session[:locale] = I18n.locale
redirect_to :back
end
def set_preferred_locale
if user_signed_in?
current_user.preferred_locale = I18n.locale.to_s
current_user.save if current_user.changed?
end
end
end
Nota: no olvide agregar algunas rutas a sus acciones change_language
Configuración regional predeterminada
Recuerde que debe establecer la configuración regional predeterminada de su aplicación. Puede hacerlo configurándolo en config/application.rb
:
config.i18n.default_locale = :de
o creando un inicializador en la carpeta config/initializers
:
# config/initializers/locale.rb
I18n.default_locale = :it
Obtener la configuración regional de la solicitud HTTP
A veces puede ser útil establecer la configuración regional de su aplicación en función de la solicitud de IP. Puedes lograrlo fácilmente usando Geocoder
. Entre las muchas cosas que hace Geocoder
, también puede indicar la location
de una request
.
Primero, agrega Geocoder
a tu Gemfile
# Gemfile
gem 'geocoder'
Geocoder
agrega location
métodos de location
y location
safe_location
al objeto estándar Rack::Request
para que pueda buscar fácilmente la ubicación de cualquier solicitud HTTP por dirección IP. Puede usar estos métodos en una before_action
en su before_action
de ApplicationController
:
class ApplicationController < ActionController::Base
before_action :set_locale_from_request
def set_locale_from_request
country_code = request.location.data["country_code"] #=> "US"
country_sym = country_code.underscore.to_sym #=> :us
# If request locale is available use it, otherwise use I18n default locale
if I18n.available_locales.include? country_sym
I18n.locale = country_sym
end
end
Tenga en cuenta que esto no funcionará en entornos de development
y test
, ya que cosas como 0.0.0.0
y localhost
son direcciones IP de Internet válidas válidas.
Limitaciones y alternativas
Geocoder
es muy potente y flexible, pero debe configurarse para funcionar con un servicio de geocodificación (ver más detalles ); Muchos de los cuales ponen límites en el uso. También vale la pena tener en cuenta que llamar a un servicio externo en cada solicitud podría afectar el rendimiento.
Para abordar esto, también puede valer la pena considerar:
1. Una solución fuera de línea
El uso de una gema como GeoIP
(ver aquí ) permite que se realicen búsquedas en un archivo de datos local. Puede haber una compensación en términos de precisión, ya que estos archivos de datos deben mantenerse actualizados.
2. Utilice CloudFlare
Las páginas servidas a través de CloudFlare tienen la opción de geocodificarse de forma transparente, con el código del país que se agrega al encabezado ( HTTP_CF_IPCOUNTRY
). Más detalles se pueden encontrar aquí .
Traducir los atributos del modelo ActiveRecord
globalize
gem es una gran solución para agregar traducciones a sus modelos de ActiveRecord
. Puedes instalarlo agregando esto a tu Gemfile
:
gem 'globalize', '~> 5.0.0'
Si está utilizando Rails 5
también necesitará agregar activemodel-serializers-xml
gem 'activemodel-serializers-xml'
Las traducciones de modelos le permiten traducir los valores de los atributos de sus modelos, por ejemplo:
class Post < ActiveRecord::Base
translates :title, :text
end
I18n.locale = :en
post.title # => Globalize rocks!
I18n.locale = :he
post.title # => גלובאלייז2 שולט!
Después de definir los atributos de su modelo que deben traducirse, debe crear una tabla de traducción a través de una migración. globalize
proporciona create_translation_table!
y drop_translation_table!
.
Para esta migración, debe usar up
y down
, y no change
. Además, para ejecutar esta migración correctamente, primero debe definir los atributos traducidos en su modelo, como se muestra arriba. Una migración adecuada para el modelo de Post
anterior es esta:
class CreatePostsTranslationTable < ActiveRecord::Migration
def up
Post.create_translation_table! title: :string, text: :text
end
def down
Post.drop_translation_table!
end
end
También puede pasar opciones para opciones específicas, como:
class CreatePostsTranslationTable < ActiveRecord::Migration
def up
Post.create_translation_table! title: :string,
text: { type: :text, null: false, default: "Default text" }
end
def down
Post.drop_translation_table!
end
end
En caso de que ya tenga datos en las columnas de traducción que necesita, puede migrarlos fácilmente a la tabla de traducciones, ajustando su migración:
class CreatePostsTranslationTable < ActiveRecord::Migration
def up
Post.create_translation_table!({
title: :string,
text: :text
}, {
migrate_data: true
})
end
def down
Post.drop_translation_table! migrate_data: true
end
end
Asegúrese de eliminar las columnas traducidas de la tabla principal después de que todos sus datos se hayan migrado de forma segura. Para eliminar automáticamente las columnas traducidas de la tabla principal después de la migración de datos, agregue la opción remove_source_columns
a la migración:
class CreatePostsTranslationTable < ActiveRecord::Migration
def up
Post.create_translation_table!({
title: :string,
text: :text
}, {
migrate_data: true,
remove_source_columns: true
})
end
def down
Post.drop_translation_table! migrate_data: true
end
end
También puede agregar nuevos campos a una tabla de traducción creada anteriormente:
class Post < ActiveRecord::Base
# Remember to add your attribute here too.
translates :title, :text, :author
end
class AddAuthorToPost < ActiveRecord::Migration
def up
Post.add_translation_fields! author: :text
end
def down
remove_column :post_translations, :author
end
end
Utilice I18n con etiquetas HTML y símbolos
# config/locales/en.yml
en:
stackoverflow:
header:
title_html: "Use <strong>I18n</strong> with Tags & Symbols"
Tenga en cuenta la adición de _html
adicional después del title
nombre.
Y en vistas,
# ERB
<h2><%= t(:title_html, scope: [:stackoverflow, :header]) %></h2>