Skip to content

Commit

Permalink
Merge pull request #92 from twitter/global_locale_setter
Browse files Browse the repository at this point in the history
Adding a global locale setter.
  • Loading branch information
camertron committed Jan 12, 2013
2 parents e4fdb37 + c33cb9b commit 1b959dc
Show file tree
Hide file tree
Showing 19 changed files with 343 additions and 49 deletions.
2 changes: 1 addition & 1 deletion README.md
Expand Up @@ -613,7 +613,7 @@ TwitterCldr.convert_locale(:msa) # :ms
TwitterCldr.convert_locale(:ms) # :ms
```

There are a few functions in TwitterCLDR that don't require a locale code, and instead use the default locale by calling `TwitterCldr.get_locale`. The `get_locale` function defers to `FastGettext.locale` when the FastGettext library is available, and falls back on :en (English) when it's not. (Twitter uses the FastGettext gem to retrieve translations efficiently in Ruby).
There are a few functions in TwitterCLDR that don't require a locale code, and instead use the default locale by calling `TwitterCldr.locale`. The `locale` function defers to `FastGettext.locale` when the FastGettext library is available, and falls back on :en (English) when it's not. (Twitter uses the FastGettext gem to retrieve translations efficiently in Ruby).

```ruby
TwitterCldr.get_locale # will return :en
Expand Down
67 changes: 59 additions & 8 deletions lib/twitter_cldr.rb
Expand Up @@ -54,23 +54,53 @@ module TwitterCldr

class << self

attr_writer :locale

def resources
@resources ||= TwitterCldr::Resources::Loader.new
end

def get_locale
if defined?(FastGettext)
locale = FastGettext.locale
locale = DEFAULT_LOCALE if locale.to_s.empty?
else
locale = DEFAULT_LOCALE
def locale
locale = supported_locale?(@locale) ? @locale : find_fallback
locale = DEFAULT_LOCALE if locale.to_s.empty?
(supported_locale?(locale) ? locale : DEFAULT_LOCALE).to_sym
end

def with_locale(locale)
raise "Unsupported locale" unless supported_locale?(locale)

begin
old_locale = @locale
@locale = locale
result = yield
ensure
@locale = old_locale
result
end
end

(supported_locale?(locale) ? locale : DEFAULT_LOCALE).to_sym
def register_locale_fallback(proc_or_locale)
case proc_or_locale
when Symbol, String, Proc
locale_fallbacks << proc_or_locale
else
raise "A locale fallback must be of type String, Symbol, or Proc."
end
nil
end

def reset_locale_fallbacks
locale_fallbacks.clear
TwitterCldr.register_locale_fallback(lambda { I18n.locale if defined?(I18n) && I18n.respond_to?(:locale) })
TwitterCldr.register_locale_fallback(lambda { FastGettext.locale if defined?(FastGettext) && FastGettext.respond_to?(:locale) })
end

def locale_fallbacks
@locale_fallbacks ||= []
end

def convert_locale(locale)
locale = locale.to_sym
locale = locale.to_sym if locale.respond_to?(:to_sym)
TWITTER_LOCALE_MAP.fetch(locale, locale)
end

Expand All @@ -86,8 +116,29 @@ def supported_locales
def supported_locale?(locale)
!!locale && supported_locales.include?(convert_locale(locale))
end

protected

def find_fallback
locale_fallbacks.reverse_each do |fallback|
result = if fallback.is_a?(Proc)
begin
fallback.call
rescue
nil
end
else
fallback
end
return result if result
end
nil
end

end

end

TwitterCldr.reset_locale_fallbacks

require 'twitter_cldr/core_ext'
4 changes: 2 additions & 2 deletions lib/twitter_cldr/formatters/plurals/rules.rb
Expand Up @@ -11,7 +11,7 @@ module Rules
class << self

def all
all_for(TwitterCldr.get_locale)
all_for(TwitterCldr.locale)
end

def all_for(locale)
Expand All @@ -20,7 +20,7 @@ def all_for(locale)
nil
end

def rule_for(number, locale = TwitterCldr.get_locale)
def rule_for(number, locale = TwitterCldr.locale)
get_resource(locale)[:rule].call(number)
rescue
:other
Expand Down
2 changes: 1 addition & 1 deletion lib/twitter_cldr/localized/localized_object.rb
Expand Up @@ -27,7 +27,7 @@ def formatter_const

def self.localize(klass)
klass.class_eval <<-LOCALIZE, __FILE__, __LINE__ + 1
def localize(locale = TwitterCldr.get_locale, options = {})
def localize(locale = TwitterCldr.locale, options = {})
#{self}.new(self, locale, options)
end
LOCALIZE
Expand Down
2 changes: 1 addition & 1 deletion lib/twitter_cldr/localized/localized_timespan.rb
Expand Up @@ -8,7 +8,7 @@ module Localized

class LocalizedTimespan < LocalizedObject
def initialize(seconds, options = {})
super(seconds, options[:locale] || TwitterCldr.get_locale, options)
super(seconds, options[:locale] || TwitterCldr.locale, options)
end

def to_s(options = {})
Expand Down
2 changes: 1 addition & 1 deletion lib/twitter_cldr/shared/calendar.rb
Expand Up @@ -32,7 +32,7 @@ class Calendar

attr_reader :locale, :calendar_type

def initialize(locale = TwitterCldr.get_locale, calendar_type = TwitterCldr::DEFAULT_CALENDAR_TYPE)
def initialize(locale = TwitterCldr.locale, calendar_type = TwitterCldr::DEFAULT_CALENDAR_TYPE)
@locale = TwitterCldr.convert_locale(locale)
@calendar_type = calendar_type
end
Expand Down
8 changes: 4 additions & 4 deletions lib/twitter_cldr/shared/languages.rb
Expand Up @@ -10,7 +10,7 @@ module Languages
class << self

def all
all_for(TwitterCldr.get_locale)
all_for(TwitterCldr.locale)
end

def all_for(code)
Expand All @@ -20,16 +20,16 @@ def all_for(code)
end

def from_code(code)
from_code_for_locale(code, TwitterCldr.get_locale)
from_code_for_locale(code, TwitterCldr.locale)
end

def from_code_for_locale(code, locale = TwitterCldr.get_locale)
def from_code_for_locale(code, locale = TwitterCldr.locale)
get_resource(locale)[:languages][TwitterCldr.convert_locale(code)]
rescue
nil
end

def translate_language(language, source_locale = :en, dest_locale = TwitterCldr.get_locale)
def translate_language(language, source_locale = :en, dest_locale = TwitterCldr.locale)
lang_code = get_resource(source_locale)[:languages].detect { |_, val| val.downcase == language.downcase }.first
get_resource(dest_locale)[:languages][lang_code] if lang_code
rescue
Expand Down
2 changes: 1 addition & 1 deletion lib/twitter_cldr/shared/numbers.rb
Expand Up @@ -9,7 +9,7 @@ module Numbers

class << self

def symbols(locale = TwitterCldr.get_locale)
def symbols(locale = TwitterCldr.locale)
get_resource(TwitterCldr.convert_locale(locale))[:symbols] rescue nil
end

Expand Down
8 changes: 4 additions & 4 deletions lib/twitter_cldr/shared/territories.rb
Expand Up @@ -10,7 +10,7 @@ module Territories
class << self

def all
all_for(TwitterCldr.get_locale)
all_for(TwitterCldr.locale)
end

def all_for(code)
Expand All @@ -20,15 +20,15 @@ def all_for(code)
end

def from_territory_code(territory_code)
from_territory_code_for_locale(territory_code, TwitterCldr.get_locale)
from_territory_code_for_locale(territory_code, TwitterCldr.locale)
end

# Returns how to say a given territory in a given locale.
#
# This method does not work for three-digit United Nation "area
# codes" (UN M.49; for example, 014 for Eastern Africa and 419 for Latin
# America).
def from_territory_code_for_locale(territory_code, locale = TwitterCldr.get_locale)
def from_territory_code_for_locale(territory_code, locale = TwitterCldr.locale)
get_resource(locale)[:territories][TwitterCldr::Utils::Territories.normalize_territory_code(territory_code)]
rescue
nil
Expand All @@ -39,7 +39,7 @@ def from_territory_code_for_locale(territory_code, locale = TwitterCldr.get_loca
# This method does not work for three-digit United Nation "area
# codes" (UN M.49; for example, 014 for Eastern Africa and 419 for Latin
# America).
def translate_territory(territory_name, source_locale = :en, dest_locale = TwitterCldr.get_locale)
def translate_territory(territory_name, source_locale = :en, dest_locale = TwitterCldr.locale)
territory_code, _ = get_resource(source_locale)[:territories].find do |_, other_territory_name|
other_territory_name.downcase == territory_name.downcase
end
Expand Down
2 changes: 1 addition & 1 deletion spec/formatters/plurals/rules_spec.rb
Expand Up @@ -60,7 +60,7 @@

describe "#all" do
it "gets rules for the default locale (usually supplied by FastGettext)" do
mock(TwitterCldr).get_locale { :ru }
mock(TwitterCldr).locale { :ru }
Rules.all.should =~ [:one, :few, :many, :other]
end
end
Expand Down
2 changes: 1 addition & 1 deletion spec/localized/localized_object_spec.rb
Expand Up @@ -81,7 +81,7 @@ def formatter_const
end

it 'uses default locale and empty options hash by default' do
mock(LocalizedClass).new(localizable_object, TwitterCldr.get_locale, {})
mock(LocalizedClass).new(localizable_object, TwitterCldr.locale, {})
localizable_object.localize
end
end
Expand Down
2 changes: 1 addition & 1 deletion spec/localized/localized_symbol_spec.rb
Expand Up @@ -12,7 +12,7 @@
describe "#as_language_code" do
it "returns the correct localized language from the symbol" do
:es.localize.as_language_code.should == "Spanish"
FastGettext.locale = :es
TwitterCldr.locale = :es
:es.localize.as_language_code.should == "español"
end

Expand Down
5 changes: 3 additions & 2 deletions spec/readme_spec.rb
Expand Up @@ -273,8 +273,9 @@ def spaces(str)
end

it "verifies locale defaults" do
TwitterCldr.get_locale.should == :en
TwitterCldr.locale.should == :en
TwitterCldr.locale = nil
FastGettext.locale = "ru"
TwitterCldr.get_locale.should == :ru
TwitterCldr.locale.should == :ru
end
end
2 changes: 1 addition & 1 deletion spec/shared/calendar_spec.rb
Expand Up @@ -18,7 +18,7 @@

describe '#initialize' do
it 'returns calendar for default locale and type' do
stub(TwitterCldr).get_locale { :fr }
stub(TwitterCldr).locale { :fr }
cal = Calendar.new

cal.locale.should == :fr
Expand Down
8 changes: 4 additions & 4 deletions spec/shared/languages_spec.rb
Expand Up @@ -21,14 +21,14 @@
Languages.translate_language("RUSSIAN", :en, :es).should match_normalized("ruso")
end

it "defaults the destination language to English (or whatever FastGettext.locale is)" do
it "defaults the destination language to English (or whatever the global locale is)" do
Languages.translate_language("Ruso", :es).should match_normalized("Russian")
Languages.translate_language("русский", :ru).should match_normalized("Russian")
end

it "defaults source and destination language to English if not given" do
Languages.translate_language("Russian").should match_normalized("Russian")
FastGettext.locale = :es
TwitterCldr.locale = :es
Languages.translate_language("Russian").should match_normalized("ruso")
end

Expand All @@ -53,7 +53,7 @@
it "should return the language in the default locale for the given locale code" do
Languages.from_code(:es).should match_normalized("Spanish")
Languages.from_code(:ru).should match_normalized("Russian")
FastGettext.locale = :es
TwitterCldr.locale = :es
Languages.from_code(:es).should match_normalized("español")
end
end
Expand All @@ -78,7 +78,7 @@
langs[:ru].should match_normalized("Russian")
langs[:de].should match_normalized("German")

FastGettext.locale = :es
TwitterCldr.locale = :es
langs = Languages.all
langs.should be_a(Hash)
langs[:ru].should match_normalized("ruso")
Expand Down
2 changes: 1 addition & 1 deletion spec/shared/numbers_spec.rb
Expand Up @@ -12,7 +12,7 @@
let(:symbols) { { :nan => 'NaN', :minus_sign => '-' } }

it 'returns numerical symbols for default locale' do
stub(TwitterCldr).get_locale { :jp }
stub(TwitterCldr).locale { :jp }
stub(TwitterCldr).get_locale_resource(:jp, :numbers) { { :jp => { :numbers => { :symbols => symbols } } } }
TwitterCldr::Shared::Numbers.symbols.should == symbols
end
Expand Down
8 changes: 4 additions & 4 deletions spec/shared/territories_spec.rb
Expand Up @@ -32,14 +32,14 @@
Territories.translate_territory("RUSSIA", :en, :es).should match_normalized("Rusia")
end

it "defaults the destination language to English (or whatever FastGettext.locale is)" do
it "defaults the destination language to English (or whatever the global locale is)" do
Territories.translate_territory("Rusia", :es).should match_normalized("Russia")
Territories.translate_territory("Россия", :ru).should match_normalized("Russia")
end

it "defaults source and destination language to English if not given" do
Territories.translate_territory("Russia").should match_normalized("Russia")
FastGettext.locale = :es
TwitterCldr.locale = :es
Territories.translate_territory("Russia").should match_normalized("Rusia")
end

Expand Down Expand Up @@ -73,7 +73,7 @@
it "should return the language in the default locale for the given locale code" do
Territories.from_territory_code(:ES).should match_normalized("Spain")
Territories.from_territory_code(:RU).should match_normalized("Russia")
FastGettext.locale = :es
TwitterCldr.locale = :es
Territories.from_territory_code(:ES).should match_normalized("España")
end
end
Expand All @@ -98,7 +98,7 @@
territories[:ru].should match_normalized("Russia")
territories[:de].should match_normalized("Germany")

FastGettext.locale = :es
TwitterCldr.locale = :es
territories = Territories.all
territories.should be_a(Hash)
territories[:ru].should match_normalized("Rusia")
Expand Down
21 changes: 19 additions & 2 deletions spec/spec_helper.rb
Expand Up @@ -21,8 +21,22 @@ def locale
@@locale
end

def locale=(value)
@@locale = value
def locale=(new_locale)
@@locale = new_locale
end
end
end

class I18n
class << self
@@locale = :en

def locale
@@locale
end

def locale=(new_locale)
@@locale = new_locale
end
end
end
Expand All @@ -35,7 +49,10 @@ def locale=(value)
config.filter_run_excluding(:slow => true) unless ENV['FULL_SPEC']

config.before(:each) do
TwitterCldr.reset_locale_fallbacks
TwitterCldr.locale = :en
FastGettext.locale = :en
I18n.locale = :en
end
end

Expand Down

0 comments on commit 1b959dc

Please sign in to comment.