Ruby on Rails
I18n - Internationalisering
Zoeken…
Syntaxis
- I18n.t ( "key")
- I18n.translate ("key") # equivalent aan
I18n.t("key")
- I18n.t ("key", count: 4)
- I18n.t ("key", param1: "Something", param2: "Else")
- I18n.t ("doesnt_exist", standaard: "key") # geef een standaard op als de sleutel ontbreekt
- I18n.locale # =>: en
- I18n.locale =: en
- I18n.default_locale # =>: en
- I18n.default_locale =: en
- t (". key") # hetzelfde als
I18n.t("key")
, maar gericht op de actie / sjabloon waar het vanaf wordt genoemd
Gebruik I18n in weergaven
Ervan uitgaande dat u dit YAML-localebestand hebt:
# config/locales/en.yml
en:
header:
title: "My header title"
en u wilt uw titelstring weergeven, kunt u dit doen
# in ERB files
<%= t('header.title') %>
# in SLIM files
= t('header.title')
I18n met argumenten
U kunt parameters doorgeven aan de I18n t
methode:
# 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) %>
En krijg de volgende output:
"12 users currently online"
pluralization
U kunt laten I18n handvat pluralization voor u, gebruik gewoon count
argument.
U moet uw locale-bestand als volgt instellen:
# config/locales/en.yml
en:
online_users:
one: "1 user is online"
other: "%{count} users are online"
En gebruik vervolgens de sleutel die u zojuist hebt gemaakt door het passeren van de count
argument om I18n.t
helper:
I18n.t("online_users", count: 1)
#=> "1 user is online"
I18n.t("online_users", count: 4)
#=> "4 users are online"
Stel de landinstelling in via verzoeken
In de meeste gevallen wilt u misschien de landinstelling I18n
instellen. Misschien wilt u de locale instellen voor de huidige sessie, de huidige gebruiker, of op basis van een URL-parameter. Dit is eenvoudig te bereiken door een before_action
in een van uw controllers te implementeren of in ApplicationController
om het in al uw controllers te hebben.
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
URL-gebaseerde
De locale
parameter kan afkomstig zijn van een URL zoals deze
http://yourapplication.com/products?locale=en
Of
http://yourapplication.com/en/products
Om dat laatste te bereiken, moet u uw routes
bewerken en een scope
:
# config/routes.rb
scope "(:locale)", locale: /en|fr/ do
resources :products
end
Door dit te doen, zal het bezoeken van http://yourapplication.com/en/products
uw landinstelling instellen op :en
. In plaats daarvan zal het bezoeken van http://yourapplication.com/fr/products
volgende instellen :fr
. Bovendien krijgt u geen routeringsfout wanneer u de :locale
parameter mist, omdat een bezoek aan http://yourapplication.com/products
de standaard I18n- landinstelling laadt.
Op sessie gebaseerd of op persistentie gebaseerd
Dit veronderstelt dat de gebruiker op een knop / taalvlag kan klikken om de taal te wijzigen. De actie kan worden doorgestuurd naar een controller die de sessie instelt op de huidige taal (en uiteindelijk de wijzigingen in een database doorvoeren als de gebruiker is verbonden)
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
U moet sanitize_language_param definiëren met uw lijst met beschikbare talen en uiteindelijk fouten afhandelen als de taal niet bestaat.
Als je heel weinig talen hebt, is het misschien de moeite waard om ze als volgt te definiëren:
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
Let op: vergeet niet om een aantal routes aan uw toe te voegen change_language
acties
Standaardlandinstelling
Vergeet niet dat u de standaardlandinstelling van uw toepassing moet instellen. U kunt dit doen door het in config/application.rb
:
config.i18n.default_locale = :de
of door een initialisatieprogramma in de map config/initializers
te maken:
# config/initializers/locale.rb
I18n.default_locale = :it
Download locale van HTTP-verzoek
Soms kan het handig zijn om de landinstelling van uw applicatie in te stellen op basis van het IP-verzoek. U kunt dit eenvoudig bereiken met Geocoder
. Onder de vele dingen die Geocoder
doet, kan het ook de location
van een request
vertellen.
Voeg eerst Geocoder
aan je Gemfile
# Gemfile
gem 'geocoder'
Geocoder
voegt location
en safe_location
methoden toe aan het standaard Rack::Request
object, zodat u eenvoudig de locatie van een HTTP-aanvraag op IP-adres kunt opzoeken. U kunt deze methoden in een eerder before_action
in uw 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
Let er op dat dit niet zal werken in development
en het test
omgevingen, zoals dingen als 0.0.0.0
en localhost
zijn geldig geldig internet IP-adressen.
Beperkingen en alternatieven
Geocoder
is zeer krachtig en flexibel, maar moet worden geconfigureerd om te werken met een geocoderingsservice (zie meer details ); veel daarvan stellen beperkingen aan het gebruik. Het is ook de moeite waard om te onthouden dat het inschakelen van een externe service bij elk verzoek van invloed kan zijn op de prestaties.
Om hier iets aan te doen, kan het ook de moeite waard zijn om te overwegen:
1. Een offline oplossing
Met behulp van een juweel zoals GeoIP
(zie hier ) kunnen zoekopdrachten worden uitgevoerd tegen een lokaal gegevensbestand. Er kan een afweging zijn qua nauwkeurigheid, omdat deze gegevensbestanden up-to-date moeten worden gehouden.
2. Gebruik CloudFlare
Pagina's die worden weergegeven via CloudFlare kunnen transparant geocoderen, waarbij de landcode wordt toegevoegd aan de header ( HTTP_CF_IPCOUNTRY
). Meer details zijn hier te vinden.
ActiveRecord-modelkenmerken vertalen
globalize
gem is een geweldige oplossing om vertalingen toe te voegen aan uw ActiveRecord
modellen. Je kunt het installeren door dit toe te voegen aan je Gemfile
:
gem 'globalize', '~> 5.0.0'
Als u Rails 5
moet u ook activemodel-serializers-xml
gem 'activemodel-serializers-xml'
Met modelvertalingen kunt u de kenmerkwaarden van uw modellen vertalen, bijvoorbeeld:
class Post < ActiveRecord::Base
translates :title, :text
end
I18n.locale = :en
post.title # => Globalize rocks!
I18n.locale = :he
post.title # => גלובאלייז2 שולט!
Nadat u uw modelattributen hebt gedefinieerd die moeten worden vertaald, moet u een vertalingstabel maken via een migratie. globalize
biedt create_translation_table!
en drop_translation_table!
.
Voor deze migratie moet u up
en down
en niet change
. Om deze migratie met succes uit te voeren, moet u eerst de vertaalde kenmerken in uw model definiëren, zoals hierboven weergegeven. Een goede migratie voor het vorige Post
model is deze:
class CreatePostsTranslationTable < ActiveRecord::Migration
def up
Post.create_translation_table! title: :string, text: :text
end
def down
Post.drop_translation_table!
end
end
U kunt ook opties doorgeven voor specifieke opties, zoals:
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
Als u al bestaande gegevens in uw vertaalkolommen nodig heeft, kunt u deze eenvoudig migreren naar de vertaaltabel door uw migratie aan te passen:
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
Zorg ervoor dat u de vertaalde kolommen uit de bovenliggende tabel verwijdert nadat al uw gegevens veilig zijn gemigreerd. Als u na de gegevensmigratie automatisch de vertaalde kolommen uit de bovenliggende tabel wilt verwijderen, voegt u de optie remove_source_columns
aan de migratie:
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
U kunt ook nieuwe velden toevoegen aan een eerder gemaakte tabel met vertalingen:
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
Gebruik I18n met HTML-tags en symbolen
# config/locales/en.yml
en:
stackoverflow:
header:
title_html: "Use <strong>I18n</strong> with Tags & Symbols"
Let op de toevoeging van extra _html
achter de title
.
En in Views,
# ERB
<h2><%= t(:title_html, scope: [:stackoverflow, :header]) %></h2>