Ruby on Rails
I18n - Internazionalizzazione
Ricerca…
Sintassi
- I18n.t ( "chiave")
- I18n.translate ("chiave") # equivalente a
I18n.t("key")
- I18n.t ("chiave", conteggio: 4)
- I18n.t ("chiave", param1: "Qualcosa", param2: "Altro")
- I18n.t ("doesnt_exist", default: "chiave") # specifica un valore predefinito se manca la chiave
- I18n.locale # =>: en
- I18n.locale =: en
- I18n.default_locale # =>: en
- I18n.default_locale =: en
- t (". chiave") # uguale a
I18n.t("key")
, ma con l'ambito dell'azione / modello chiamato da
Usa I18n in visualizzazioni
Supponendo che tu abbia questo file locale YAML:
# config/locales/en.yml
en:
header:
title: "My header title"
e vuoi mostrare la stringa del titolo, puoi farlo
# in ERB files
<%= t('header.title') %>
# in SLIM files
= t('header.title')
I18n con argomenti
È possibile passare parametri al metodo 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) %>
E ottieni il seguente risultato:
"12 users currently online"
pluralizzazione
Puoi lasciare che I18n gestisca la pluralizzazione per te, basta usare l'argomento count
.
Devi impostare il tuo file locale in questo modo:
# config/locales/en.yml
en:
online_users:
one: "1 user is online"
other: "%{count} users are online"
Quindi utilizzare la chiave appena creata passando l'argomento count
I18n.t
:
I18n.t("online_users", count: 1)
#=> "1 user is online"
I18n.t("online_users", count: 4)
#=> "4 users are online"
Imposta la locale attraverso le richieste
Nella maggior parte dei casi, potresti voler impostare la locale I18n
. Si potrebbe desiderare di impostare le impostazioni internazionali per la sessione corrente, l'utente corrente o in base a un parametro URL. Ciò è facilmente ottenibile implementando un'azione before_action
in uno dei controller o in ApplicationController
per averlo in tutti i controller.
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
basata URL
Il parametro locale
potrebbe provenire da un URL come questo
http://yourapplication.com/products?locale=en
O
http://yourapplication.com/en/products
Per raggiungere quest'ultimo, è necessario modificare i routes
, aggiungendo un scope
:
# config/routes.rb
scope "(:locale)", locale: /en|fr/ do
resources :products
end
In questo modo, visitando http://yourapplication.com/en/products
verranno impostate le impostazioni internazionali su :en
. Invece, visitando http://yourapplication.com/fr/products
lo imposterai a :fr
. Inoltre, non si ottiene un errore di routing quando manca il parametro :locale
, poiché visitando http://yourapplication.com/products
verrà caricata la locale I18n predefinita.
Basato su sessione o basato sulla persistenza
Ciò presuppone che l'utente possa fare clic su un pulsante / flag lingua per cambiare la lingua. L'azione può essere instradata a un controller che imposta la sessione sulla lingua corrente (e eventualmente persiste le modifiche in un database se l'utente è connesso)
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
Devi definire sanitize_language_param con l'elenco delle lingue disponibili e infine gestire gli errori nel caso in cui la lingua non esista.
Se hai pochissime lingue, potrebbe valere la pena di definirle in questo modo:
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: non dimenticare di aggiungere alcuni percorsi alle tue azioni change_language
Impostazioni internazionali predefinite
Ricordare che è necessario impostare le impostazioni locali predefinite dell'applicazione. Puoi farlo impostandolo in config/application.rb
:
config.i18n.default_locale = :de
o creando un inizializzatore nella cartella config/initializers
:
# config/initializers/locale.rb
I18n.default_locale = :it
Ottieni impostazioni locali dalla richiesta HTTP
A volte può essere utile impostare le impostazioni locali dell'applicazione in base all'IP della richiesta. Puoi facilmente ottenerlo usando Geocoder
. Tra le molte cose che fa Geocoder
, può anche indicare la location
di una request
.
Per prima cosa, aggiungi Geocoder
al tuo Gemfile
# Gemfile
gem 'geocoder'
Geocoder
aggiunge i metodi location
e safe_location
standard Rack::Request
modo da poter facilmente cercare la posizione di qualsiasi richiesta HTTP per indirizzo IP. È possibile utilizzare questi metodi in un'azione before_action
in 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
Attenzione che questo non funzionerà negli ambienti di development
e test
, poiché cose come 0.0.0.0
e localhost
sono validi indirizzi IP Internet validi.
Limitazioni e alternative
Geocoder
è molto potente e flessibile, ma deve essere configurato per funzionare con un servizio di geocoding (vedi maggiori dettagli ); molti dei quali pongono limiti all'uso. Vale anche la pena ricordare che chiamare un servizio esterno a ogni richiesta potrebbe influire sulle prestazioni.
Per affrontarli, può anche valere la pena considerare:
1. Una soluzione offline
L'utilizzo di una gemma come GeoIP
(vedi qui ) consente di effettuare ricerche su un file di dati locale. Ci può essere un trade-off in termini di accuratezza, dal momento che questi file di dati devono essere mantenuti aggiornati.
2. Usa CloudFlare
Le pagine pubblicate tramite CloudFlare hanno la possibilità di essere geocodificate in modo trasparente, con l'aggiunta del codice paese all'intestazione ( HTTP_CF_IPCOUNTRY
). Maggiori dettagli possono essere trovati qui .
Tradurre gli attributi del modello ActiveRecord
globalize
gem è un'ottima soluzione per aggiungere traduzioni ai tuoi modelli ActiveRecord
. Puoi installarlo aggiungendo questo al tuo Gemfile
:
gem 'globalize', '~> 5.0.0'
Se stai usando Rails 5
dovrai anche aggiungere activemodel-serializers-xml
gem 'activemodel-serializers-xml'
Le traduzioni di modelli ti consentono di tradurre i valori degli attributi dei tuoi modelli, ad esempio:
class Post < ActiveRecord::Base
translates :title, :text
end
I18n.locale = :en
post.title # => Globalize rocks!
I18n.locale = :he
post.title # => גלובאלייז2 שולט!
Dopo aver definito gli attributi del modello che devono essere tradotti, è necessario creare una tabella di conversione, attraverso una migrazione. globalize
fornisce create_translation_table!
e drop_translation_table!
.
Per questa migrazione è necessario utilizzare up
e down
, e non change
. Inoltre, per eseguire correttamente questa migrazione, devi prima definire gli attributi tradotti nel tuo modello, come mostrato sopra. Una migrazione corretta per il modello Post
precedente è questa:
class CreatePostsTranslationTable < ActiveRecord::Migration
def up
Post.create_translation_table! title: :string, text: :text
end
def down
Post.drop_translation_table!
end
end
Puoi anche passare opzioni per opzioni specifiche, come:
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
Se hai già dati esistenti nelle tue colonne di traduzione che necessitano, puoi facilmente migrarlo alla tabella delle traduzioni, regolando la tua migrazione:
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
Assicurati di eliminare le colonne tradotte dalla tabella padre dopo che tutti i tuoi dati sono stati migrati in modo sicuro. Per rimuovere automaticamente le colonne tradotte dalla tabella padre dopo la migrazione dei dati, aggiungi l'opzione remove_source_columns
alla migrazione:
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
Puoi anche aggiungere nuovi campi a una tabella di traduzioni creata in precedenza:
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
Usa I18n con tag e simboli HTML
# config/locales/en.yml
en:
stackoverflow:
header:
title_html: "Use <strong>I18n</strong> with Tags & Symbols"
Nota l'aggiunta di _html
extra dopo il title
del nome.
E in Views,
# ERB
<h2><%= t(:title_html, scope: [:stackoverflow, :header]) %></h2>