Ruby on Rails
I18n - internacjonalizacja
Szukaj…
Składnia
- I18n.t („klucz”)
- I18n.translate („klucz”) # odpowiednik
I18n.t("key")
- I18n.t („klucz”, liczba: 4)
- I18n.t („klucz”, param1: „Coś”, param2: „Else”)
- I18n.t („doesnt_exist”, domyślnie: „klucz”) # podaj wartość domyślną, jeśli brakuje klucza
- I18n.locale # =>: en
- I18n.locale =: en
- I18n.default_locale # =>: en
- I18n.default_locale =: en
- t („. klucz”) # to samo co
I18n.t("key")
, ale zakres działania / szablonu, z którego jest wywoływany
Użyj I18n w widokach
Zakładając, że masz ten plik ustawień regionalnych YAML:
# config/locales/en.yml
en:
header:
title: "My header title"
i chcesz wyświetlić ciąg tytułu, możesz to zrobić
# in ERB files
<%= t('header.title') %>
# in SLIM files
= t('header.title')
I18n z argumentami
Możesz przekazać parametry do metody 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) %>
I uzyskaj następujące dane wyjściowe:
"12 users currently online"
Pluralizacja
Możesz pozwolić I18n zająć się pluralizacją, po prostu użyj argumentu count
.
Musisz skonfigurować plik ustawień regionalnych w ten sposób:
# config/locales/en.yml
en:
online_users:
one: "1 user is online"
other: "%{count} users are online"
A następnie użyj klucza, który właśnie utworzyłeś, przekazując argument count
do pomocnika I18n.t
:
I18n.t("online_users", count: 1)
#=> "1 user is online"
I18n.t("online_users", count: 4)
#=> "4 users are online"
Ustaw ustawienia regionalne za pomocą żądań
W większości przypadków możesz chcieć ustawić I18n
regionalne I18n
. Można chcieć ustawić ustawienia regionalne dla bieżącej sesji, bieżącego użytkownika lub na podstawie parametru adresu URL. Można to łatwo osiągnąć poprzez zaimplementowanie działania before_action
w jednym ze swoich kontrolerów lub w ApplicationController
aby mieć go we wszystkich swoich kontrolerach.
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
Na podstawie adresu URL
Parametry locale
mogą pochodzić z adresu URL takiego jak ten
http://yourapplication.com/products?locale=en
Lub
http://yourapplication.com/en/products
Aby osiągnąć to drugie, musisz edytować swoje routes
, dodając scope
:
# config/routes.rb
scope "(:locale)", locale: /en|fr/ do
resources :products
end
W ten sposób odwiedzając http://yourapplication.com/en/products
ustawisz swoje ustawienia regionalne na :en
. Zamiast tego, odwiedzając http://yourapplication.com/fr/products
ustawi się na :fr
. Ponadto nie wystąpi błąd routingu, gdy brakuje parametru :locale
, ponieważ odwiedzając stronę http://yourapplication.com/products
, załadowane zostaną domyślne ustawienia regionalne I18n .
Oparte na sesji lub oparte na trwałości
Zakłada się, że użytkownik może kliknąć przycisk / flagę języka, aby zmienić język. Akcja może kierować do kontrolera, który ustawia sesję na bieżący język (i ostatecznie utrwalić zmiany w bazie danych, jeśli użytkownik jest podłączony)
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
Musisz zdefiniować sanitize_language_param za pomocą listy dostępnych języków i ostatecznie obsłużyć błędy, jeśli język nie istnieje.
Jeśli masz bardzo mało języków, warto zdefiniować je w następujący sposób:
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
Uwaga: nie zapomnij dodać niektórych tras do swoich akcji change_language
Domyślne ustawienia regionalne
Pamiętaj, że musisz ustawić domyślne ustawienia regionalne aplikacji. Możesz to zrobić, ustawiając go w config/application.rb
:
config.i18n.default_locale = :de
lub tworząc inicjator w folderze config/initializers
:
# config/initializers/locale.rb
I18n.default_locale = :it
Uzyskaj ustawienia regionalne z żądania HTTP
Czasami może być przydatne ustawienie ustawień regionalnych aplikacji na podstawie adresu IP żądania. Możesz to łatwo osiągnąć za pomocą Geocoder
. Wśród wielu rzeczy, które robi Geocoder
, może również określić location
request
.
Najpierw dodaj Geocoder
do swojego Gemfile
# Gemfile
gem 'geocoder'
Geocoder
dodaje metody location
i safe_location
do standardowego obiektu Rack::Request
dzięki czemu można łatwo wyszukać lokalizację dowolnego żądania HTTP według adresu IP. before_action
metod można użyć w działaniu before_action
w 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
Uważaj, że to nie zadziała w środowisku development
i test
, ponieważ takie rzeczy jak 0.0.0.0
i localhost
są prawidłowymi poprawnymi internetowymi adresami IP.
Ograniczenia i alternatywy
Geocoder
jest bardzo wydajny i elastyczny, ale musi być skonfigurowany do pracy z usługą geokodowania (zobacz więcej szczegółów ); wiele z nich ogranicza wykorzystanie. Warto również pamiętać, że wywołanie usługi zewnętrznej na każde żądanie może mieć wpływ na wydajność.
Aby rozwiązać te problemy, warto również rozważyć:
1. Rozwiązanie offline
Użycie klejnotu, takiego jak GeoIP
(patrz tutaj ), umożliwia wyszukiwanie w lokalnym pliku danych. Może wystąpić kompromis w zakresie dokładności, ponieważ te pliki danych muszą być aktualizowane.
2. Użyj CloudFlare
Strony obsługiwane przez CloudFlare mają opcję geokodowania przezroczystego, z kodem kraju dodawanym do nagłówka ( HTTP_CF_IPCOUNTRY
). Więcej szczegółów można znaleźć tutaj .
Tłumaczenie atrybutów modelu ActiveRecord
globalize
klejnotów to świetne rozwiązanie do dodawania tłumaczeń do modeli ActiveRecord
. Możesz go zainstalować, dodając to do swojego Gemfile
:
gem 'globalize', '~> 5.0.0'
Jeśli używasz Rails 5
musisz również dodać activemodel-serializers-xml
gem 'activemodel-serializers-xml'
Tłumaczenie modeli pozwala tłumaczyć wartości atrybutów modeli, na przykład:
class Post < ActiveRecord::Base
translates :title, :text
end
I18n.locale = :en
post.title # => Globalize rocks!
I18n.locale = :he
post.title # => גלובאלייז2 שולט!
Po zdefiniowaniu atrybutów modelu, które muszą zostać przetłumaczone, musisz utworzyć tabelę tłumaczeń poprzez migrację. globalize
zapewnia create_translation_table!
i drop_translation_table!
.
W przypadku tej migracji należy korzystać w up
iw down
, a nie change
. Ponadto, aby pomyślnie przeprowadzić tę migrację, musisz najpierw zdefiniować przetłumaczone atrybuty w swoim modelu, jak pokazano powyżej. Prawidłowa migracja dla poprzedniego modelu Post
jest następująca:
class CreatePostsTranslationTable < ActiveRecord::Migration
def up
Post.create_translation_table! title: :string, text: :text
end
def down
Post.drop_translation_table!
end
end
Możesz także przekazać opcje dla określonych opcji, takich jak:
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
Jeśli masz już istniejące dane w potrzebnych kolumnach tłumaczenia, możesz łatwo migrować je do tabeli tłumaczeń, dostosowując migrację:
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
Pamiętaj, aby upuścić przetłumaczone kolumny z tabeli nadrzędnej po bezpiecznej migracji wszystkich danych. Aby automatycznie usunąć przetłumaczone kolumny z tabeli nadrzędnej po migracji danych, dodaj do migracji opcję remove_source_columns
:
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
Możesz także dodać nowe pola do wcześniej utworzonej tabeli tłumaczeń:
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
Użyj I18n z tagami i symbolami HTML
# config/locales/en.yml
en:
stackoverflow:
header:
title_html: "Use <strong>I18n</strong> with Tags & Symbols"
Zwróć uwagę na dodanie dodatkowego _html
po title
nazwy.
I w widokach
# ERB
<h2><%= t(:title_html, scope: [:stackoverflow, :header]) %></h2>