Top Banner
The Ruby on Rails The Ruby on Rails I18n Core API I18n Core API PRESENTED BY PRESENTED BY -Neeraj Kumar -Neeraj Kumar
58

The Ruby On Rails I18n Core Api

Jan 19, 2015

Download

Documents

neerajkumar09

My presentation on I18n during Ruby India Conference 2010, Bangalore, India
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: The Ruby On Rails I18n Core Api

The Ruby on Rails The Ruby on Rails I18n Core APII18n Core API

PRESENTED BYPRESENTED BY

-Neeraj Kumar-Neeraj Kumar

Page 2: The Ruby On Rails I18n Core Api

IntroductionIntroduction

• English – Default Language.English – Default Language.• GettextGettext• Tough Task – transform your ROR App Tough Task – transform your ROR App

into its regional language & providing a into its regional language & providing a tool to solve all problems at once.tool to solve all problems at once.

Page 3: The Ruby On Rails I18n Core Api

• Provides easy-to-use and extensible framework.Provides easy-to-use and extensible framework.• Translating Translating

- to a single custom language other than English.- to a single custom language other than English.

- for providing multi-language support.- for providing multi-language support.

Page 4: The Ruby On Rails I18n Core Api

• To abstract all strings and other locale To abstract all strings and other locale specific bits (such as date or currency specific bits (such as date or currency formats) out of your application. The formats) out of your application. The process of “localization” means to provide process of “localization” means to provide translations and localized formats for translations and localized formats for these bits.these bits.

• Sven FuchsSven Fuchs• Shipped with rails (started with rails-2.2)Shipped with rails (started with rails-2.2)

Page 5: The Ruby On Rails I18n Core Api

• In the process of internationalizing: In the process of internationalizing: – Ensure you have support for i18nEnsure you have support for i18n– Tell Rails where to find locale Tell Rails where to find locale

dictionariesdictionaries– Tell Rails how to set, preserve and Tell Rails how to set, preserve and

switch localeswitch locale

Page 6: The Ruby On Rails I18n Core Api

SetupSetup for RoR App for RoR App

• Configure the I18n ModuleConfigure the I18n Module– .rb and .yml + .rb and .yml + translations load pathtranslations load path, ,

automatically.automatically.– translations load path (translations load path (I18n.load_pathI18n.load_path) )

- will be loaded automatically and - will be loaded automatically and available in your application.available in your application.

Page 7: The Ruby On Rails I18n Core Api

– environment.rbenvironment.rb - instructions to - instructions to customize the locale directory and customize the locale directory and default locale.e.g.default locale.e.g.

# config.i18n.load_path << # config.i18n.load_path << Dir[File.join(RAILS_ROOT, 'my', Dir[File.join(RAILS_ROOT, 'my', 'locales', '*.{rb,yml}')]'locales', '*.{rb,yml}')]

# config.i18n.default_locale = :de # config.i18n.default_locale = :de

en: en:

hello: "Hello hello: "Hello world"world"

Page 8: The Ruby On Rails I18n Core Api

• Setting and Passing the LocaleSetting and Passing the Locale

- For more locales - to set and pass the - For more locales - to set and pass the locale between requests.locale between requests.

- Don't use session or cookies to store the - Don't use session or cookies to store the chosen locale.chosen locale.

Page 9: The Ruby On Rails I18n Core Api

before_filter :set_localedef set_locale

# if params[:locale] is nil then I18n.default_locale will be used

I18n.locale = params[:locale]end

- URL : - URL : http://example.com/books?locale=pthttp://example.com/books?locale=pt - will load Portuguese localization.- will load Portuguese localization.

Page 10: The Ruby On Rails I18n Core Api

• Locale setting from the URL ParamsLocale setting from the URL Params

- link_to( books_url(:locale => - link_to( books_url(:locale => I18n.locale)) - tedious and probably I18n.locale)) - tedious and probably impossible.impossible.

- For 'centralizing dynamic decisions - For 'centralizing dynamic decisions about the URLs' in its about the URLs' in its ApplicationController#default_url_optionApplicationController#default_url_options.s.

Page 11: The Ruby On Rails I18n Core Api

# app/controllers/application_controller.rbdef default_url_options(options = {})

logger.debug “default_url_options is passed options:

#{options.inspect}\n”{:locale => I18n.locale}

end

- Every helper method dependent on url_for - Every helper method dependent on url_for automatically include the locale in the query automatically include the locale in the query stringstring..

Page 12: The Ruby On Rails I18n Core Api

# config/routes.rbmap.resources :books, :path_prefix => '/:locale'

# => www.example.com/nl/booksmap.root '/:locale', :controller => “dashboard”

Page 13: The Ruby On Rails I18n Core Api

- Drawback of default_url_options - Drawback of default_url_options implementation pass the :id implementation pass the :id

option, e.g. link_to option, e.g. link_to 'show', book_url(:id 'show', book_url(:id => book)=> book)

Page 14: The Ruby On Rails I18n Core Api

• Locale setting from the Domain NameLocale setting from the Domain Name

- advantages- advantages–Locale, an obvious part of URLLocale, an obvious part of URL–Trivial to implementTrivial to implement– Intuitively grasp the language of Intuitively grasp the language of

content before loadingcontent before loading–Search engines like content in Search engines like content in

different languages at different different languages at different domains.domains.

Page 15: The Ruby On Rails I18n Core Api

before_filter :set_locale

def set_localeI18n.locale = extract_locale_from_uri

end

Page 16: The Ruby On Rails I18n Core Api

def extract_locale_from_tldparsed_locale = request.host.split('.').lastI18n.available_locales.include?

(parsed_locale.to_sym) ? parsed_locale : nilend

- parsed_locale = request.host.split('.').first - parsed_locale = request.host.split('.').first to set the locale from subdomain.to set the locale from subdomain.

Page 17: The Ruby On Rails I18n Core Api

• Locale setting from the Client Supplied Locale setting from the Client Supplied InformationInformation

- information can come from - information can come from – Users preferred language (set in Users preferred language (set in

their browser)their browser)– Users geographical location Users geographical location

inferred from IPinferred from IP– By choosing locale in your By choosing locale in your

application interface and saving to application interface and saving to the profile.the profile.

Page 18: The Ruby On Rails I18n Core Api

def set_localelogger.debug = “* Accept-Language:

#{request.env['HTTP_ACCEPT_LANGUAGE']}”I18n.locale =

extract_locale_from_accept_language_headerend

Page 19: The Ruby On Rails I18n Core Api

def extract_locale_from_accept_language_headerrequest.env['HTTP_ACCEPT_LANGUAGE'].scan(/

^[a-z]{2}/).firstend

- Using GeoIP (or similar) Database – - Using GeoIP (or similar) Database – GeoIP Lite CountryGeoIP Lite Country

- User Profile- User Profile

Page 20: The Ruby On Rails I18n Core Api

en:activerecord:

models:user: fooadmin: bar

attributes:user:

login: “Handle” # => will translate User attribute “login” as “Handle”

Active Record Model TranslationsActive Record Model Translations

Page 21: The Ruby On Rails I18n Core Api

en:activerecord:

errors:messages:

blank: “can not has nothing”# => #<User id:nil, etc># => u.valid?# => false# => u.errors.on(:name)# => “can not has nothing”

– Error Messages ScopeError Messages Scope - Active - Active Record Validation Error Messages Record Validation Error Messages TranslationTranslation

Page 22: The Ruby On Rails I18n Core Api

– Active Record will look up this key in Active Record will look up this key in the namespacesthe namespaces– activerecord.errors.models.activerecord.errors.models.

[model_name].attributes.[model_name].attributes.[attribute_name] [attribute_name]

– activerecord.errors.models.activerecord.errors.models.[model_name] [model_name]

– activerecord.errors.messages activerecord.errors.messages

Page 23: The Ruby On Rails I18n Core Api

en:activerecord:

errors:messages:

already_registered: “u already is {{model}}”# => u.errors.on(:email)# => “u already is foo”

– Error Message InterpolationError Message Interpolation– Count can be used for PluralizationCount can be used for Pluralization

Page 24: The Ruby On Rails I18n Core Api

– Translation for the Active Record Translation for the Active Record error_messages_for Helpererror_messages_for Helper

en: activerecord: errors: template: header: one: “1 error prohibted this {{model}} from being saved” other: “{{count}} errors prohibted this {{model}} from being saved” body: “There were problems with the following fields:”

Page 25: The Ruby On Rails I18n Core Api

Anatomy of GemAnatomy of Gemi18n

i18n

i18ni18n

backendbackend

core_extcore_ext helpers

helpers localeslocales

backendbackend

exceptionsexceptions

gettextgettext

helpershelpers

localelocale

i18ni18n

versionversion

localelocale

gettextgettext

fallbacksfallbacks

tagtag

Page 26: The Ruby On Rails I18n Core Api

active_recordactive_recordInterpolation

compiler

Interpolationcompiler

Interpolationcompiler

Interpolationcompiler

Interpolationcompiler

Interpolationcompiler

Interpolationcompiler

Interpolationcompiler

Interpolationcompiler

Interpolationcompiler

Interpolationcompiler

Interpolationcompiler

Interpolationcompiler

Interpolationcompiler

fastfast

gettextgettext

helpershelpers

Interpolationcompiler

Interpolationcompiler

linkslinks

metadatametadata

simplesimple

active_recordactive_record

basebase

cachecache

cascadercascader

chainchain

cldrcldr

fallbacksfallbacks pluralization

pluralization

missingmissing

translationtranslation

store_procsstore_procs

backend

Page 27: The Ruby On Rails I18n Core Api

i18n.rbi18n.rb

• get and set methods for default_locale.get and set methods for default_locale.

def default_locale(locale)@@default_locale = locale.to_sym rescue

nilend

• Get method for locale - either Get method for locale - either default_locale or locale in default_locale or locale in Thread.currentThread.current hash.hash.

Page 28: The Ruby On Rails I18n Core Api

i18n.ri18n.rbb

• Set method for locale - set the locale in Set method for locale - set the locale in Thread.currentThread.current

• Returns the current backend.Returns the current backend.

def backend@@backend ||= Backend::Simple.new

end

• Set method for current backend.Set method for current backend.

Page 29: The Ruby On Rails I18n Core Api

simple.simple.rbrb • Makes easier to extend the Simple Makes easier to extend the Simple

backend's behaviour by including backend's behaviour by including modules e.g. modules e.g. I18n::Backend::Simple.send(:include, I18n::Backend::Simple.send(:include, I18n::Backend::Pluralization).I18n::Backend::Pluralization).

module I18nmodule Backend

class Simpleinclude Base

endend

end

Page 30: The Ruby On Rails I18n Core Api

i18n.rbi18n.rb

def available_locales@@available_locales ||=

backend.available_localesend

Page 31: The Ruby On Rails I18n Core Api

I18n.rbI18n.rb

• Default scope separator method (i.e Default scope separator method (i.e default_separator) default_separator) – set your separator set your separator – return the separator.return the separator.

• Default is '.'Default is '.'

Page 32: The Ruby On Rails I18n Core Api

I18n.rbI18n.rb

• Exception handler method (i.e. Exception handler method (i.e. exception_handler)exception_handler)– set your exception handlerset your exception handler– return the current exception handler.return the current exception handler.

• Default is :default_exception_handler Default is :default_exception_handler private method.private method.

Page 33: The Ruby On Rails I18n Core Api

I18n.rbI18n.rb

def default_exception_handler(exception, locale, key, options)

return exception.message if MissingTranslationData === exception

raise exceptionend

Page 34: The Ruby On Rails I18n Core Api

I18n.rbI18n.rb

• load_path=(load_path) method - set load load_path=(load_path) method - set load path instance.path instance.

• load_path methodload_path method– *.rb*.rb and contain plain and contain plain RubyRuby Hashes.Hashes.– *.yml*.yml and contain and contain YAMLYAML data. data.

Page 35: The Ruby On Rails I18n Core Api

I18n.rbI18n.rb

• Class method config returns I18n Class method config returns I18n configuration objectconfiguration object

def configThread.current[:i18n_config] ||= I18n::Config.new

end

• method config=(value) sets I18n method config=(value) sets I18n configuration object.configuration object.

Page 36: The Ruby On Rails I18n Core Api

I18n.rbI18n.rb

• Method to reload the translations.Method to reload the translations.• Main method Main method translatetranslate and and localizelocalize• I18n.t :message I18n.t :message I18n.t 'message' I18n.t 'message'

Page 37: The Ruby On Rails I18n Core Api

I18n.rbI18n.rb

• Translation method – scope options, Translation method – scope options, interpolation, pluralization, defaults interpolation, pluralization, defaults

• :scope option – one or many keys - scope :scope option – one or many keys - scope for a translation keyfor a translation key

I18n.t :invalid, :scope => [:active_record, :error_messages] # => I18n.translation :invalid :active_record.error_messages.invalid

Page 38: The Ruby On Rails I18n Core Api

I18n.rbI18n.rb

• InterpolationInterpolationI18n.t :foo, :bar => 'baz' #=> 'foo baz'

I18n.t :foo, :count => 1 #=> 'foo'I18n.t :foo, :count => 0 #=> 'foos'I18n.t :foo, :count => 2 #=> 'foos'

• PluralizationPluralization

• DefaultsDefaults

I18n.t :foo, :default => 'bar'

Page 39: The Ruby On Rails I18n Core Api

I18n.rbI18n.rb

def translate(&args)options = args.pop if args.last.is_a?(Hash)key = args.shiftlocale = options && options.delete(:locale) || config.localeraises = options && options.delete(:raise)config.backend.translate(locale, key, options || {})rescue I18n::ArgumentError => exceptionraise exception if raiseshandle_exception(exception, locale, key, options)

endalias :t :translate

Page 40: The Ruby On Rails I18n Core Api

I18n.rbI18n.rb

def localize(object, options = {})locale = options.delete(:locale) || config.localeformat = options.delete(:format) || :defaultconfig.backend.localize(locale, object, format, options)

endalias :l :localize

Page 41: The Ruby On Rails I18n Core Api

base.rbbase.rb

• load_translations method - accepts list of load_translations method - accepts list of paths of translation files.paths of translation files.

def load_translations(*filenames)filenames.each { |filename|

load_file(filename) }end

Page 42: The Ruby On Rails I18n Core Api

base.rbbase.rb

def load_file(filename)type = File.extname(filename).tr('.', '').downcaseraise UnknownFileType.new(type, filename) unless respond_to?(:”load_#(type)”)data = send(:”load_#(type)”, filename)data.each { |locale, d| merge_translation(locale, d) }

end

Page 43: The Ruby On Rails I18n Core Api

base.rbbase.rb

def store_translations(locale, data, options = {})merge_translations(locale, data, options)

end

Page 44: The Ruby On Rails I18n Core Api

def merge_translations(locale, data, options = {})locale = locale.to_symtranslations[locale] ||= {}separator = options[:separator] || I18n.default_separatordata = unwind_keys(data, separator)data = deep_symbolized_keys(data)

merger = proc do |key, v1, v2|Hash === v1 && Hash === v2 ?

v1.merge(v2, &merger) : (v2 || v1)endtranslations[locale].merge!(data, &merger)

end

base.rbbase.rb

Page 45: The Ruby On Rails I18n Core Api

base.rbbase.rb

def translate(locale, key, options = {}) raise InvalidLocale.new(locale) unless locale return key.map { |k| translate(locale, k, options) } if key.is_a?(Array)

if options.empty? entry = resolve(locale, key, lookup(locale, key), options) raise(I18n::MissingTranslationData.new(locale, key, options)) if entry.nil?

Page 46: The Ruby On Rails I18n Core Api

else count, scope, default = options.values_at(:count, :scope, :default) values = options.reject { |name, value| RESERVED_KEYS.include?(name) }

entry = lookup(locale, key, scope, options) entry = entry.nil? && default ? default(locale, key, default, options) : resolve(locale, key, entry, options)

base.rbbase.rb

Page 47: The Ruby On Rails I18n Core Api

raise(I18n::MissingTranslationData.new(locale, key, options)) if entry.nil?

entry = pluralize(locale, entry, count) if count

entry = interpolate(locale, entry, values) if values

end entryend

base.rbbase.rb

Page 48: The Ruby On Rails I18n Core Api

base.rbbase.rb

• look_up method look_up method – looks up the translation from the looks up the translation from the

translations hash. translations hash. – Splits keys or scopes containing dots Splits keys or scopes containing dots

into multiple keys e.g. currency.format into multiple keys e.g. currency.format - %w(currency format).- %w(currency format).

Page 49: The Ruby On Rails I18n Core Api

base.rbase.rbb

• localize methodlocalize method

case match when '%a' then I18n.t(:"date.abbr_day_names”, :locale => locale, :format => format)[object.wday] when '%A' then I18n.t(:"date.day_names”, :locale => locale, :format => format)[object.wday] when '%b' then I18n.t(:"date.abbr_month_names", :locale => locale, :format => format)[object.mon]

Page 50: The Ruby On Rails I18n Core Api

when '%B' then I18n.t(:"date.month_names", :locale => locale, :format => format)[object.mon] when '%p' then I18n.t(:"time.#{object.hour < 12 ? :am : :pm}", :locale => locale, :format => format) if object.respond_to? :hour end

base.rbbase.rb

Page 51: The Ruby On Rails I18n Core Api

CustomizationCustomization

• Different BackendsDifferent Backends– I18n::Backend::SimpleI18n::Backend::Simple

– shipped with Active Support of shipped with Active Support of vendor directory, work for english vendor directory, work for english or similar languages.or similar languages.– capable of reading translations capable of reading translations

but cannot dynamically store but cannot dynamically store them to any format.them to any format.

Page 52: The Ruby On Rails I18n Core Api

MissingTranslationData # no translation was found for the requested keyInvalidLocale # the locale set to I18n.locale is invalid (e.g. nil)

• Different Exception HandlersDifferent Exception Handlers

Page 53: The Ruby On Rails I18n Core Api

- customization – e.g. the default exception - customization – e.g. the default exception handling does not allow to catch missing handling does not allow to catch missing translation during automated test easilytranslation during automated test easily..

Page 54: The Ruby On Rails I18n Core Api

– I18nI18n– own backendown backend–makes easy to exchange the makes easy to exchange the

Simple backend implementation Simple backend implementation with that to fits better with your with that to fits better with your need.need.

I18n.backend = Globalize::Backend::Static.new

Page 55: The Ruby On Rails I18n Core Api

module I18ndef just_raise_that_exception(*args)

raise args.firstend

end

I18n.exception_handler = :just_raise_that_exception

Page 56: The Ruby On Rails I18n Core Api

ReferencesReferences• http://guides.rails.info/i18n.htmlhttp://guides.rails.info/i18n.html

• http://rails-i18n.org/wikihttp://rails-i18n.org/wiki

• http://iain.nl/2008/09/translating-activerecord/http://iain.nl/2008/09/translating-activerecord/

• http://github.com/svenfuchs/rails-i18nhttp://github.com/svenfuchs/rails-i18n

• http://rails-i18n.org/wiki/wikipages/i18n-rails-guidehttp://rails-i18n.org/wiki/wikipages/i18n-rails-guide

• http://www.artweb-design.de/2008/7/18/the-ruby-on-http://www.artweb-design.de/2008/7/18/the-ruby-on-rails-i18n-core-apirails-i18n-core-api

Page 57: The Ruby On Rails I18n Core Api

Questions?Questions?

Page 58: The Ruby On Rails I18n Core Api

Thank You!Thank You!