Add Globalize2 so that we get some nice fall backs to other languages when a translation is missing in the requested language.

This commit is contained in:
Shaun McDonald 2009-05-27 15:39:14 +00:00
parent 6ba51da46e
commit 283a3e9ba9
42 changed files with 2670 additions and 0 deletions

View file

@ -0,0 +1,175 @@
require File.join( File.dirname(__FILE__), '..', 'test_helper' )
require 'globalize/backend/chain'
module Globalize
module Backend
class Dummy
def translate(locale, key, options = {})
end
end
end
end
class ChainedTest < ActiveSupport::TestCase
test "instantiates a chained backend and sets test as backend" do
assert_nothing_raised { I18n.chain_backends }
assert_instance_of Globalize::Backend::Chain, I18n.backend
end
test "passes all given arguments to the chained backends #initialize method" do
Globalize::Backend::Chain.expects(:new).with(:spec, :simple)
I18n.chain_backends :spec, :simple
end
test "passes all given arguments to #add assuming that they are backends" do
# no idea how to spec that
end
end
class AddChainedTest < ActiveSupport::TestCase
def setup
I18n.backend = Globalize::Backend::Chain.new
end
test "accepts an instance of a backend" do
assert_nothing_raised { I18n.backend.add Globalize::Backend::Dummy.new }
assert_instance_of Globalize::Backend::Dummy, I18n.backend.send(:backends).first
end
test "accepts a class and instantiates the backend" do
assert_nothing_raised { I18n.backend.add Globalize::Backend::Dummy }
assert_instance_of Globalize::Backend::Dummy, I18n.backend.send(:backends).first
end
test "accepts a symbol, constantizes test as a backend class and instantiates the backend" do
assert_nothing_raised { I18n.backend.add :dummy }
assert_instance_of Globalize::Backend::Dummy, I18n.backend.send(:backends).first
end
test "accepts any number of backend instances, classes or symbols" do
assert_nothing_raised { I18n.backend.add Globalize::Backend::Dummy.new, Globalize::Backend::Dummy, :dummy }
assert_instance_of Globalize::Backend::Dummy, I18n.backend.send(:backends).first
assert_equal [ Globalize::Backend::Dummy, Globalize::Backend::Dummy, Globalize::Backend::Dummy ],
I18n.backend.send(:backends).map{|backend| backend.class }
end
end
class TranslateChainedTest < ActiveSupport::TestCase
def setup
I18n.locale = :en
I18n.backend = Globalize::Backend::Chain.new
@first_backend = I18n::Backend::Simple.new
@last_backend = I18n::Backend::Simple.new
I18n.backend.add @first_backend
I18n.backend.add @last_backend
end
test "delegates #translate to all backends in the order they were added" do
@first_backend.expects(:translate).with(:en, :foo, {})
@last_backend.expects(:translate).with(:en, :foo, {})
I18n.translate :foo
end
test "returns the result from #translate from the first backend if test's not nil" do
@first_backend.store_translations :en, {:foo => 'foo from first backend'}
@last_backend.store_translations :en, {:foo => 'foo from last backend'}
result = I18n.translate :foo
assert_equal 'foo from first backend', result
end
test "returns the result from #translate from the second backend if the first one returned nil" do
@first_backend.store_translations :en, {}
@last_backend.store_translations :en, {:foo => 'foo from last backend'}
result = I18n.translate :foo
assert_equal 'foo from last backend', result
end
test "looks up a namespace from all backends and merges them (if a result is a hash and no count option is present)" do
@first_backend.store_translations :en, {:foo => {:bar => 'bar from first backend'}}
@last_backend.store_translations :en, {:foo => {:baz => 'baz from last backend'}}
result = I18n.translate :foo
assert_equal( {:bar => 'bar from first backend', :baz => 'baz from last backend'}, result )
end
test "raises a MissingTranslationData exception if no translation was found" do
assert_raise( I18n::MissingTranslationData ) { I18n.translate :not_here, :raise => true }
end
test "raises an InvalidLocale exception if the locale is nil" do
assert_raise( I18n::InvalidLocale ) { Globalize::Backend::Chain.new.translate nil, :foo }
end
test "bulk translates a number of keys from different backends" do
@first_backend.store_translations :en, {:foo => 'foo from first backend'}
@last_backend.store_translations :en, {:bar => 'bar from last backend'}
result = I18n.translate [:foo, :bar]
assert_equal( ['foo from first backend', 'bar from last backend'], result )
end
test "still calls #translate on all the backends" do
@last_backend.expects :translate
I18n.translate :not_here, :default => 'default'
end
test "returns a given default string when no backend returns a translation" do
result = I18n.translate :not_here, :default => 'default'
assert_equal 'default', result
end
end
class CustomLocalizeBackend < I18n::Backend::Simple
def localize(locale, object, format = :default)
"result from custom localize backend" if locale == 'custom'
end
end
class LocalizeChainedTest < ActiveSupport::TestCase
def setup
I18n.locale = :en
I18n.backend = Globalize::Backend::Chain.new
@first_backend = CustomLocalizeBackend.new
@last_backend = I18n::Backend::Simple.new
I18n.backend.add @first_backend
I18n.backend.add @last_backend
@time = Time.now
end
test "delegates #localize to all backends in the order they were added" do
@first_backend.expects(:localize).with(:en, @time, :default)
@last_backend.expects(:localize).with(:en, @time, :default)
I18n.localize @time
end
test "returns the result from #localize from the first backend if test's not nil" do
@last_backend.expects(:localize).never
result = I18n.localize @time, :locale => 'custom'
assert_equal 'result from custom localize backend', result
end
test "returns the result from #localize from the second backend if the first one returned nil" do
@last_backend.expects(:localize).returns "value from last backend"
result = I18n.localize @time
assert_equal 'value from last backend', result
end
end
class NamespaceChainedTest < ActiveSupport::TestCase
def setup
@backend = Globalize::Backend::Chain.new
end
test "returns false if the given result is not a Hash" do
assert !@backend.send(:namespace_lookup?, 'foo', {})
end
test "returns false if a count option is present" do
assert !@backend.send(:namespace_lookup?, {:foo => 'foo'}, {:count => 1})
end
test "returns true if the given result is a Hash AND no count option is present" do
assert @backend.send(:namespace_lookup?, {:foo => 'foo'}, {})
end
end

View file

@ -0,0 +1,63 @@
require File.join( File.dirname(__FILE__), '..', 'test_helper' )
require 'globalize/backend/pluralizing'
class PluralizingTest < ActiveSupport::TestCase
def setup
@backend = Globalize::Backend::Pluralizing.new
@cz_pluralizer = lambda{|c| c == 1 ? :one : (2..4).include?(c) ? :few : :other }
end
test "#pluralizer returns the pluralizer for a given locale if defined" do
assert_instance_of Proc, @backend.pluralizer(:en)
end
test "#pluralizer returns the default pluralizer if no pluralizer is defined for the given locale" do
assert_equal @backend.pluralizer(:en), @backend.pluralizer(:de)
end
test "#add_pluralizer allows to store a pluralizer per locale" do
assert_nothing_raised { @backend.add_pluralizer(:cz, @cz_pluralizer) }
assert_equal @cz_pluralizer, @backend.pluralizer(:cz)
end
end
class PluralizePluralizingTest < ActiveSupport::TestCase
def setup
@backend = Globalize::Backend::Pluralizing.new
@cz_pluralizer = lambda{|c| c == 1 ? :one : (2..4).include?(c) ? :few : :other }
@backend.store_translations :en, :foo => {:one => 'one en foo', :other => 'many en foos'}
@backend.store_translations :cz, :foo => {:one => 'one cz foo', :few => 'few cz foos', :other => 'many cz foos'}
end
test "looks up the :one translation when count is 1" do
assert_equal 'one en foo', @backend.translate(:en, :foo, :count => 1)
end
test "looks up the :other translation when count is 2" do
assert_equal 'many en foos', @backend.translate(:en, :foo, :count => 2)
end
end
class CzPluralizingTest < ActiveSupport::TestCase
def setup
@backend = Globalize::Backend::Pluralizing.new
@cz_pluralizer = lambda{|c| c == 1 ? :one : (2..4).include?(c) ? :few : :other }
@backend.store_translations :en, :foo => {:one => 'one en foo', :other => 'many en foos'}
@backend.store_translations :cz, :foo => {:one => 'one cz foo', :few => 'few cz foos', :other => 'many cz foos'}
@backend.add_pluralizer(:cz, @cz_pluralizer)
end
test "looks up the :one translation when count is 1 (:cz)" do
assert_equal 'one cz foo', @backend.translate(:cz, :foo, :count => 1)
end
test "looks up the :few translation when count is 2 (:cz)" do
assert_equal 'few cz foos', @backend.translate(:cz, :foo, :count => 2)
end
test "looks up the :other translation when count is 5 (:cz)" do
assert_equal 'many cz foos', @backend.translate(:cz, :foo, :count => 5)
end
end

View file

@ -0,0 +1,143 @@
require File.join( File.dirname(__FILE__), '..', 'test_helper' )
require 'globalize/backend/static'
require 'globalize/translation'
require 'action_view'
include ActionView::Helpers::NumberHelper
I18n.locale = :'en-US' # Need to set this, since I18n defaults to 'en'
class StaticTest < ActiveSupport::TestCase
def setup
I18n.backend = Globalize::Backend::Static.new
translations = {:"en-US" => {:foo => "foo in en-US", :boz => 'boz', :buz => {:bum => 'bum'}},
:"en" => {:bar => "bar in en"},
:"de-DE" => {:baz => "baz in de-DE"},
:"de" => {:boo => "boo in de", :number => { :currency => { :format => { :unit => '€', :format => '%n %u'}}}}}
translations.each do |locale, data|
I18n.backend.store_translations locale, data
end
I18n.fallbacks.map :"de-DE" => :"en-US", :he => :en
end
test "returns an instance of Translation:Static" do
translation = I18n.translate :foo
assert_instance_of Globalize::Translation::Static, translation
end
test "returns the translation in en-US if present" do
assert_equal "foo in en-US", I18n.translate(:foo, :locale => :"en-US")
end
test "returns the translation in en if en-US is not present" do
assert_equal "bar in en", I18n.translate(:bar, :locale => :"en-US")
end
test "returns the translation in de-DE if present" do
assert_equal "baz in de-DE", I18n.translate(:baz, :locale => :"de-DE")
end
test "returns the translation in de if de-DE is not present" do
assert_equal "boo in de", I18n.translate(:boo, :locale => :"de-DE")
end
test "returns the translation in en-US if none of de-DE and de are present" do
assert_equal "foo in en-US", I18n.translate(:foo, :locale => :"de-DE")
end
test "returns the translation in en if none of de-DE, de and en-US are present" do
assert_equal "bar in en", I18n.translate(:bar, :locale => :"de-DE")
end
test "returns the translation in en if none in he is present" do
assert_equal "bar in en", I18n.translate(:bar, :locale => :he)
end
test "returns the given default String when the key is not present for any locale" do
assert_equal "default", I18n.translate(:missing, :default => "default")
end
test "returns the fallback translation for the key if present for a fallback locale" do
I18n.backend.store_translations :de, :non_default => "non_default in de"
assert_equal "non_default in de", I18n.translate(:non_default, :default => "default", :locale => :"de-DE")
end
test "returns an array of translations" do
assert_instance_of Array, I18n.translate([:foo, :boz])
end
test "returns an array of instances of Translation::Static" do
assert_equal [Globalize::Translation::Static], I18n.translate([:foo, :boz]).map(&:class).uniq
end
test "returns a hash of translations" do
assert_instance_of Hash, I18n.translate(:"buz")
end
test "returns an array of translations 2" do
assert_equal [Globalize::Translation::Static], I18n.translate(:"buz").values.map(&:class)
end
test "returns currency properly formated" do
currency = number_to_currency(10)
assert_equal "$10.00", currency
end
test "returns currency properly formated for locale" do
currency = number_to_currency(10, :locale => :'de')
assert_equal "10.000 €", currency
end
test "returns currency properly formated from parameters" do
currency = number_to_currency(10, :format => "%n %u", :unit => '€')
assert_equal "10.00 €", currency
end
test "makes sure interpolation does not break even with False as string" do
assert_equal "translation missing: en, support, array, skip_last_comma", I18n.translate(:"support.array.skip_last_comma")
end
end
class TranslationStaticTest < ActiveSupport::TestCase
def setup
I18n.backend = Globalize::Backend::Static.new
translations = {
:greeting => "Hi {{name}}",
:messages => { :one => "You have one message.", :other => "You have {{count}} messages."}
}
I18n.backend.store_translations :"en", translations
end
def greeting
I18n.translate :greeting, :locale => :"en-US", :name => "Joshua"
end
test "stores the actual locale" do
assert_equal :en, greeting.locale
end
test "stores the requested locale" do
assert_equal :'en-US', greeting.requested_locale
end
test "stores the requested key" do
assert_equal :greeting, greeting.key
end
test "stores the options given to #translate" do
assert_equal( {:name => "Joshua"}, greeting.options )
end
test "stores the original translation before test was interpolated" do
assert_equal "Hi {{name}}", greeting.original
end
test "stores the plural_key :one if pluralized as such" do
message = I18n.translate :messages, :locale => :"en-US", :count => 1
assert_equal :one, message.plural_key
end
test "stores the plural_key :other if pluralized as such" do
messages = I18n.translate :messages, :locale => :"en-US", :count => 2
assert_equal :other, messages.plural_key
end
end

View file

@ -0,0 +1,2 @@
en-US:
from-all-file: From the "all" file.

View file

@ -0,0 +1,2 @@
de-DE:
from-locale-file: Aus der Locale Datei.

View file

@ -0,0 +1,2 @@
en-US:
from-locale-file: From the locale file.

View file

@ -0,0 +1,2 @@
en-US:
from-locale-dir: From the locale directory.

View file

@ -0,0 +1,2 @@
fi-FI:
from-locale-dir: Locale hakemistosta.

View file

View file

@ -0,0 +1,11 @@
# This schema creates tables without columns for the translated fields
ActiveRecord::Schema.define do
create_table :blogs, :force => true do |t|
t.string :name
end
create_table :posts, :force => true do |t|
t.references :blog
end
end

View file

@ -0,0 +1,24 @@
class Post < ActiveRecord::Base
translates :subject, :content
validates_presence_of :subject
end
class Blog < ActiveRecord::Base
has_many :posts, :order => 'id ASC'
end
class Parent < ActiveRecord::Base
translates :content
end
class Child < Parent
end
class Comment < ActiveRecord::Base
validates_presence_of :content
belongs_to :post
end
class TranslatedComment < Comment
translates :content
end

View file

@ -0,0 +1,39 @@
ActiveRecord::Schema.define do
create_table :blogs, :force => true do |t|
t.string :description
end
create_table :posts, :force => true do |t|
t.references :blog
end
create_table :post_translations, :force => true do |t|
t.string :locale
t.references :post
t.string :subject
t.text :content
end
create_table :parents, :force => true do |t|
end
create_table :parent_translations, :force => true do |t|
t.string :locale
t.references :parent
t.text :content
t.string :type
end
create_table :comments, :force => true do |t|
t.references :post
end
create_table :translated_comment_translations, :force => true do |t|
t.string :locale
t.references :comment
t.string :subject
t.text :content
end
end

View file

@ -0,0 +1,36 @@
require File.join( File.dirname(__FILE__), '..', 'test_helper' )
require 'globalize/i18n/missing_translations_log_handler'
class MissingTranslationsTest < ActiveSupport::TestCase
test "defines I18n.missing_translations_logger accessor" do
assert I18n.respond_to?(:missing_translations_logger)
end
test "defines I18n.missing_translations_logger= writer" do
assert I18n.respond_to?(:missing_translations_logger=)
end
end
class TestLogger < String
def warn(msg) self.concat msg; end
end
class LogMissingTranslationsTest < ActiveSupport::TestCase
def setup
@locale, @key, @options = :en, :foo, {}
@exception = I18n::MissingTranslationData.new(@locale, @key, @options)
@logger = TestLogger.new
I18n.missing_translations_logger = @logger
end
test "still returns the exception message for MissingTranslationData exceptions" do
result = I18n.send(:missing_translations_log_handler, @exception, @locale, @key, @options)
assert_equal 'translation missing: en, foo', result
end
test "logs the missing translation to I18n.missing_translations_logger" do
I18n.send(:missing_translations_log_handler, @exception, @locale, @key, @options)
assert_equal 'translation missing: en, foo', @logger
end
end

View file

@ -0,0 +1,49 @@
require File.join( File.dirname(__FILE__), 'test_helper' )
require 'globalize/load_path'
class LoadPathTest < ActiveSupport::TestCase
def setup
@plugin_dir = "#{File.dirname(__FILE__)}/.."
@locale_dir = "#{File.dirname(__FILE__)}/data/locale"
@load_path = Globalize::LoadPath.new
end
test "returns glob patterns for all locales and ruby + yaml files by default" do
patterns = %w(locales/all.rb
locales/*.rb
locales/*/**/*.rb
locales/all.yml
locales/*.yml
locales/*/**/*.yml)
assert_equal patterns, @load_path.send(:patterns, 'locales')
end
test "returns the glob patterns for registered locales and extensions" do
@load_path.locales = [:en, :de]
@load_path.extensions = [:sql]
patterns = %w(locales/all.sql
locales/en.sql
locales/en/**/*.sql
locales/de.sql
locales/de/**/*.sql)
assert_equal patterns, @load_path.send(:patterns, 'locales')
end
test "expands paths using yml as a default file extension" do
@load_path << @locale_dir
expected = %w(all.yml de-DE.yml en-US.yml en-US/module.yml fi-FI/module.yml root.yml)
assert_equal expected, @load_path.map{|path| path.sub("#{@locale_dir}\/", '')}
end
test "appends new paths to the collection so earlier collected paths preceed later collected ones" do
@load_path.locales = [:root]
@load_path << "#{@plugin_dir}/lib/locale"
@load_path << @locale_dir
expected = %W(#{@plugin_dir}/lib/locale/root.yml
#{@locale_dir}/all.yml
#{@locale_dir}/root.yml)
assert_equal expected, @load_path
end
end

View file

@ -0,0 +1,154 @@
require File.join( File.dirname(__FILE__), '..', 'test_helper' )
require 'globalize/locale/fallbacks'
include Globalize::Locale
I18n.default_locale = :'en-US' # This has to be set explicitly, no longer default for I18n
class FallbacksTest < ActiveSupport::TestCase
def setup
I18n.fallbacks = Fallbacks.new
end
def teardown
I18n.default_locale = :'en-US'
end
test "#[] caches computed results" do
I18n.fallbacks['en']
assert_equal( { :en => [:en, :"en-US", :root] }, I18n.fallbacks )
end
test "#defaults always reflect the I18n.default_locale if no default has been set manually" do
I18n.default_locale = :'en-US'
assert_equal( [:'en-US', :en, :root], I18n.fallbacks.defaults )
end
test "#defaults always reflect a manually passed default locale if any" do
I18n.fallbacks = Fallbacks.new(:'fi-FI')
assert_equal( [:'fi-FI', :fi, :root], I18n.fallbacks.defaults )
I18n.default_locale = :'de-DE'
assert_equal( [:'fi-FI', :fi, :root], I18n.fallbacks.defaults )
end
test "#defaults allows to set multiple defaults" do
I18n.fallbacks = Fallbacks.new(:'fi-FI', :'se-FI')
assert_equal( [:'fi-FI', :fi, :'se-FI', :se, :root], I18n.fallbacks.defaults )
end
end
class NoMappingFallbacksTest < ActiveSupport::TestCase
def setup
@fallbacks = Fallbacks.new(:'en-US')
end
test "returns [:es, :en-US, :root] for :es" do
assert_equal [:es, :"en-US", :en, :root], @fallbacks[:es]
end
test "returns [:es-ES, :es, :en-US, :root] for :es-ES" do
assert_equal [:"es-ES", :es, :"en-US", :en, :root], @fallbacks[:"es-ES"]
end
test "returns [:es-MX, :es, :en-US, :root] for :es-MX" do
assert_equal [:"es-MX", :es, :"en-US", :en, :root], @fallbacks[:"es-MX"]
end
test "returns [:es-Latn-ES, :es-Latn, :es, :en-US, :root] for :es-Latn-ES" do
assert_equal [:"es-Latn-ES", :"es-Latn", :es, :"en-US", :en, :root], @fallbacks[:'es-Latn-ES']
end
test "returns [:en, :en-US, :root] for :en" do
assert_equal [:en, :"en-US", :root], @fallbacks[:en]
end
test "returns [:en-US, :en, :root] for :en-US (special case: locale == default)" do
assert_equal [:"en-US", :en, :root], @fallbacks[:"en-US"]
end
end
class CaMappingFallbacksTest < ActiveSupport::TestCase
# Most people who speak Catalan also live in Spain, so test is safe to assume
# that they also speak Spanish as spoken in Spain.
def setup
@fallbacks = Fallbacks.new(:'en-US')
@fallbacks.map :ca => :"es-ES"
end
test "returns [:ca, :es-ES, :es, :en-US, :root] for :ca" do
assert_equal [:ca, :"es-ES", :es, :"en-US", :en, :root], @fallbacks[:ca]
end
test "returns [:ca-ES, :ca, :es-ES, :es, :en-US, :root] for :ca-ES" do
assert_equal [:"ca-ES", :ca, :"es-ES", :es, :"en-US", :en, :root], @fallbacks[:"ca-ES"]
end
end
class ArMappingFallbacksTest < ActiveSupport::TestCase
# People who speak Arabic as spoken in Palestine often times also speak
# Hebrew as spoken in Israel. However test is in no way safe to assume that
# everybody who speaks Arabic also speaks Hebrew.
def setup
@fallbacks = Fallbacks.new(:'en-US')
@fallbacks.map :"ar-PS" => :"he-IL"
end
test "returns [:ar, :en-US, :root] for :ar" do
assert_equal [:ar, :"en-US", :en, :root], @fallbacks[:ar]
end
test "returns [:ar-EG, :ar, :en-US, :root] for :ar-EG" do
assert_equal [:"ar-EG", :ar, :"en-US", :en, :root], @fallbacks[:"ar-EG"]
end
test "returns [:ar-PS, :ar, :he-IL, :he, :en-US, :root] for :ar-PS" do
assert_equal [:"ar-PS", :ar, :"he-IL", :he, :"en-US", :en, :root], @fallbacks[:"ar-PS"]
end
end
class SmsMappingFallbacksTest < ActiveSupport::TestCase
# Sami people live in several scandinavian countries. In Finnland many people
# know Swedish and Finnish. Thus, test can be assumed that Sami living in
# Finnland also speak Swedish and Finnish.
def setup
@fallbacks = Fallbacks.new(:'en-US')
@fallbacks.map :sms => [:"se-FI", :"fi-FI"]
end
test "returns [:sms-FI, :sms, :se-FI, :se, :fi-FI, :fi, :en-US, :root] for :sms-FI" do
assert_equal [:"sms-FI", :sms, :"se-FI", :se, :"fi-FI", :fi, :"en-US", :en, :root], @fallbacks[:"sms-FI"]
end
end
class DeAtMappingFallbacksTest < ActiveSupport::TestCase
def setup
@fallbacks = Fallbacks.new(:'en-US')
@fallbacks.map :"de-AT" => :"de-DE"
end
test "returns [:de, :en-US, :root] for de" do
assert_equal [:de, :"en-US", :en, :root], @fallbacks[:"de"]
end
test "returns [:de-DE, :de, :en-US, :root] for de-DE" do
assert_equal [:"de-DE", :de, :"en-US", :en, :root], @fallbacks[:"de-DE"]
end
test "returns [:de-AT, :de, :de-DE, :en-US, :root] for de-AT" do
assert_equal [:"de-AT", :de, :"de-DE", :"en-US", :en, :root], @fallbacks[:"de-AT"]
end
end
class DeMappingFallbacksTest < ActiveSupport::TestCase
def setup
@fallbacks = Fallbacks.new(:'en-US')
@fallbacks.map :de => :en, :he => :en
end
test "returns [:de, :en, :root] for :de" do
assert_equal [:de, :en, :"en-US", :root], @fallbacks[:de]
end
test "returns [:he, :en, :root] for :de" do
assert_equal [:he, :en, :"en-US", :root], @fallbacks[:he]
end
end

View file

@ -0,0 +1,130 @@
require File.join( File.dirname(__FILE__), '..', 'test_helper' )
require 'globalize/locale/language_tag'
include Globalize::Locale
class LanguageTagTest < ActiveSupport::TestCase
test "given a valid tag 'de' returns an LanguageTag from #tag" do
assert_instance_of LanguageTag, LanguageTag.tag('de')
end
test "given a valid tag 'de' returns an array of subtags" do
assert_equal ['de', nil, nil, nil, nil, nil, nil], LanguageTag::SimpleParser.match('de')
end
test "given a valid tag 'de-DE' returns an array of subtags" do
assert_equal ['de', nil, 'DE', nil, nil, nil, nil], LanguageTag::SimpleParser.match('de-DE')
end
test "given a valid lowercase tag 'de-latn-de-variant-x-phonebk' returns an array of subtags" do
assert_equal ['de', 'latn', 'de', 'variant', nil, 'x-phonebk', nil],
LanguageTag::SimpleParser.match('de-latn-de-variant-x-phonebk')
end
test "given a valid uppercase tag 'DE-LATN-DE-VARIANT-X-PHONEBK' returns an array of subtags" do
assert_equal ['DE', 'LATN', 'DE', 'VARIANT', nil, 'X-PHONEBK', nil],
LanguageTag::SimpleParser.match('DE-LATN-DE-VARIANT-X-PHONEBK')
end
test "given an invalid tag 'a-DE' test returns false" do
assert !LanguageTag::SimpleParser.match('a-DE')
end
test "given an invalid tag 'de-419-DE' test returns false" do
assert !LanguageTag::SimpleParser.match('de-419-DE')
end
end
class DeLatnLanguageTagTest < ActiveSupport::TestCase
def setup
subtags = %w(de Latn DE variant a-ext x-phonebk i-klingon)
@tag = LanguageTag.new *subtags
end
test "returns 'de' as the language subtag in lowercase" do
assert_equal 'de', @tag.language
end
test "returns 'Latn' as the script subtag in titlecase" do
assert_equal 'Latn', @tag.script
end
test "returns 'DE' as the region subtag in uppercase" do
assert_equal 'DE', @tag.region
end
test "returns 'variant' as the variant subtag in lowercase" do
assert_equal 'variant', @tag.variant
end
test "returns 'a-ext' as the extension subtag" do
assert_equal 'a-ext', @tag.extension
end
test "returns 'x-phonebk' as the privateuse subtag" do
assert_equal 'x-phonebk', @tag.privateuse
end
test "returns 'i-klingon' as the grandfathered subtag" do
assert_equal 'i-klingon', @tag.grandfathered
end
test "returns a formatted tag string from #to_s" do
assert_equal 'de-Latn-DE-variant-a-ext-x-phonebk-i-klingon', @tag.to_s
end
test "returns an array containing the formatted subtags from #to_a" do
assert_equal %w(de Latn DE variant a-ext x-phonebk i-klingon), @tag.to_a
end
end
class InheritanceLanguageTagTest < ActiveSupport::TestCase
test "returns 'de-Latn-DE-variant-a-ext-x-phonebk' as the parent of 'de-Latn-DE-variant-a-ext-x-phonebk-i-klingon'" do
tag = LanguageTag.new *%w(de Latn DE variant a-ext x-phonebk i-klingon)
assert_equal 'de-Latn-DE-variant-a-ext-x-phonebk', tag.parent.to_s
end
test "returns 'de-Latn-DE-variant-a-ext' as the parent of 'de-Latn-DE-variant-a-ext-x-phonebk'" do
tag = LanguageTag.new *%w(de Latn DE variant a-ext x-phonebk)
assert_equal 'de-Latn-DE-variant-a-ext', tag.parent.to_s
end
test "returns 'de-Latn-DE-variant' as the parent of 'de-Latn-DE-variant-a-ext'" do
tag = LanguageTag.new *%w(de Latn DE variant a-ext)
assert_equal 'de-Latn-DE-variant', tag.parent.to_s
end
test "returns 'de-Latn-DE' as the parent of 'de-Latn-DE-variant'" do
tag = LanguageTag.new *%w(de Latn DE variant)
assert_equal 'de-Latn-DE', tag.parent.to_s
end
test "returns 'de-Latn' as the parent of 'de-Latn-DE'" do
tag = LanguageTag.new *%w(de Latn DE)
assert_equal 'de-Latn', tag.parent.to_s
end
test "returns 'de' as the parent of 'de-Latn'" do
tag = LanguageTag.new *%w(de Latn)
assert_equal 'de', tag.parent.to_s
end
# TODO RFC4647 says: "If no language tag matches the request, the "default" value is returned."
# where should we set the default language?
# test "returns '' as the parent of 'de'" do
# tag = LanguageTag.new *%w(de)
# assert_equal '', tag.parent.to_s
# end
test "returns an array of 5 parents for 'de-Latn-DE-variant-a-ext-x-phonebk-i-klingon'" do
parents = %w(de-Latn-DE-variant-a-ext-x-phonebk-i-klingon
de-Latn-DE-variant-a-ext-x-phonebk
de-Latn-DE-variant-a-ext
de-Latn-DE-variant
de-Latn-DE
de-Latn
de)
tag = LanguageTag.new *%w(de Latn DE variant a-ext x-phonebk i-klingon)
assert_equal parents, tag.parents.map{|tag| tag.to_s}
end
end

View file

@ -0,0 +1,73 @@
require File.join( File.dirname(__FILE__), '..', '..', 'test_helper' )
require 'active_record'
require 'globalize/model/active_record'
# Hook up model translation
ActiveRecord::Base.send(:include, Globalize::Model::ActiveRecord::Translated)
# Load Post model
require File.join( File.dirname(__FILE__), '..', '..', 'data', 'post' )
class MigrationTest < ActiveSupport::TestCase
def setup
reset_db! File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'data', 'no_globalize_schema.rb'))
end
test 'globalize table added' do
assert !Post.connection.table_exists?( :post_translations )
Post.create_translation_table! :subject => :string, :content => :text
assert Post.connection.table_exists?( :post_translations )
columns = Post.connection.columns( :post_translations )
assert locale = columns.detect {|c| c.name == 'locale' }
assert_equal :string, locale.type
assert subject = columns.detect {|c| c.name == 'subject' }
assert_equal :string, subject.type
assert content = columns.detect {|c| c.name == 'content' }
assert_equal :text, content.type
assert post_id = columns.detect {|c| c.name == 'post_id' }
assert_equal :integer, post_id.type
assert created_at = columns.detect {|c| c.name == 'created_at' }
assert_equal :datetime, created_at.type
assert updated_at = columns.detect {|c| c.name == 'updated_at' }
assert_equal :datetime, updated_at.type
end
test 'globalize table dropped' do
assert !Post.connection.table_exists?( :post_translations )
Post.create_translation_table! :subject => :string, :content => :text
assert Post.connection.table_exists?( :post_translations )
Post.drop_translation_table!
assert !Post.connection.table_exists?( :post_translations )
end
test 'exception on untranslated field inputs' do
assert_raise Globalize::Model::UntranslatedMigrationField do
Post.create_translation_table! :subject => :string, :content => :text, :bogus => :string
end
end
test 'exception on missing field inputs' do
assert_raise Globalize::Model::MigrationMissingTranslatedField do
Post.create_translation_table! :content => :text
end
end
test 'exception on bad input type' do
assert_raise Globalize::Model::BadMigrationFieldType do
Post.create_translation_table! :subject => :string, :content => :integer
end
end
test 'create_translation_table! should not be called on non-translated models' do
assert_raise NoMethodError do
Blog.create_translation_table! :name => :string
end
end
test 'drop_translation_table! should not be called on non-translated models' do
assert_raise NoMethodError do
Blog.drop_translation_table!
end
end
end

View file

@ -0,0 +1,75 @@
require File.join( File.dirname(__FILE__), '..', '..', 'test_helper' )
require 'active_record'
require 'globalize/model/active_record'
# Hook up model translation
ActiveRecord::Base.send(:include, Globalize::Model::ActiveRecord::Translated)
# Load Post model
require File.join( File.dirname(__FILE__), '..', '..', 'data', 'post' )
class StiTranslatedTest < ActiveSupport::TestCase
def setup
I18n.locale = :'en-US'
I18n.fallbacks.clear
reset_db! File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'data', 'schema.rb'))
end
def teardown
I18n.fallbacks.clear
end
test "works with simple dynamic finders" do
foo = Child.create :content => 'foo'
Child.create :content => 'bar'
child = Child.find_by_content('foo')
assert_equal foo, child
end
test 'change attribute on globalized model' do
child = Child.create :content => 'foo'
assert_equal [], child.changed
child.content = 'bar'
assert_equal [ 'content' ], child.changed
child.content = 'baz'
assert_member 'content', child.changed
end
test 'change attribute on globalized model after locale switching' do
child = Child.create :content => 'foo'
assert_equal [], child.changed
child.content = 'bar'
I18n.locale = :de
assert_equal [ 'content' ], child.changed
end
test 'fallbacks with lots of locale switching' do
I18n.fallbacks.map :'de-DE' => [ :'en-US' ]
child = Child.create :content => 'foo'
I18n.locale = :'de-DE'
assert_equal 'foo', child.content
I18n.locale = :'en-US'
child.update_attribute :content, 'bar'
I18n.locale = :'de-DE'
assert_equal 'bar', child.content
end
test "saves all locales, even after locale switching" do
child = Child.new :content => 'foo'
I18n.locale = 'de-DE'
child.content = 'bar'
I18n.locale = 'he-IL'
child.content = 'baz'
child.save
I18n.locale = 'en-US'
child = Child.first
assert_equal 'foo', child.content
I18n.locale = 'de-DE'
assert_equal 'bar', child.content
I18n.locale = 'he-IL'
assert_equal 'baz', child.content
end
end

View file

@ -0,0 +1,458 @@
require File.join( File.dirname(__FILE__), '..', '..', 'test_helper' )
require 'active_record'
require 'globalize/model/active_record'
# Hook up model translation
ActiveRecord::Base.send(:include, Globalize::Model::ActiveRecord::Translated)
# Load Post model
require File.join( File.dirname(__FILE__), '..', '..', 'data', 'post' )
class TranslatedTest < ActiveSupport::TestCase
def setup
I18n.locale = :'en-US'
I18n.fallbacks.clear
reset_db! File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'data', 'schema.rb'))
ActiveRecord::Base.locale = nil
end
def teardown
I18n.fallbacks.clear
end
test "modifiying translated fields" do
post = Post.create :subject => 'foo'
assert_equal 'foo', post.subject
post.subject = 'bar'
assert_equal 'bar', post.subject
end
test "modifiying translated fields while switching locales" do
post = Post.create :subject => 'foo'
assert_equal 'foo', post.subject
I18n.locale = :'de-DE'
post.subject = 'bar'
assert_equal 'bar', post.subject
I18n.locale = :'en-US'
assert_equal 'foo', post.subject
I18n.locale = :'de-DE'
post.subject = 'bar'
end
test "has post_translations" do
post = Post.create
assert_nothing_raised { post.globalize_translations }
end
test "has German post_translations" do
I18n.locale = :de
post = Post.create :subject => 'foo'
assert_equal 1, post.globalize_translations.size
I18n.locale = :en
assert_equal 1, post.globalize_translations.size
end
test "returns the value passed to :subject" do
post = Post.new
assert_equal 'foo', (post.subject = 'foo')
end
test "translates subject and content into en-US" do
post = Post.create :subject => 'foo', :content => 'bar'
assert_equal 'foo', post.subject
assert_equal 'bar', post.content
assert post.save
post.reload
assert_equal 'foo', post.subject
assert_equal 'bar', post.content
end
test "finds a German post" do
post = Post.create :subject => 'foo (en)', :content => 'bar'
I18n.locale = 'de-DE'
post = Post.first
post.subject = 'baz (de)'
post.save
assert_equal 'baz (de)', Post.first.subject
I18n.locale = :'en-US'
assert_equal 'foo (en)', Post.first.subject
end
test "saves an English post and loads test correctly" do
assert_nil Post.first
post = Post.create :subject => 'foo', :content => 'bar'
assert post.save
post = Post.first
assert_equal 'foo', post.subject
assert_equal 'bar', post.content
end
test "updates an attribute" do
post = Post.create :subject => 'foo', :content => 'bar'
post.update_attribute :subject, 'baz'
assert_equal 'baz', Post.first.subject
end
test "update_attributes failure" do
post = Post.create :subject => 'foo', :content => 'bar'
assert !post.update_attributes( { :subject => '' } )
assert_nil post.reload.attributes['subject']
assert_equal 'foo', post.subject
end
test "validates presence of :subject" do
post = Post.new
assert !post.save
post = Post.new :subject => 'foo'
assert post.save
end
test "returns the value for the correct locale, after locale switching" do
post = Post.create :subject => 'foo'
I18n.locale = 'de-DE'
post.subject = 'bar'
post.save
I18n.locale = 'en-US'
post = Post.first
assert_equal 'foo', post.subject
I18n.locale = 'de-DE'
assert_equal 'bar', post.subject
end
test "keeping one field in new locale when other field is changed" do
I18n.fallbacks.map 'de-DE' => [ 'en-US' ]
post = Post.create :subject => 'foo'
I18n.locale = 'de-DE'
post.content = 'bar'
assert_equal 'foo', post.subject
end
test "modifying non-required field in a new locale" do
I18n.fallbacks.map 'de-DE' => [ 'en-US' ]
post = Post.create :subject => 'foo'
I18n.locale = 'de-DE'
post.content = 'bar'
assert post.save
end
test "returns the value for the correct locale, after locale switching, without saving" do
post = Post.create :subject => 'foo'
I18n.locale = 'de-DE'
post.subject = 'bar'
I18n.locale = 'en-US'
assert_equal 'foo', post.subject
I18n.locale = 'de-DE'
assert_equal 'bar', post.subject
end
test "saves all locales, even after locale switching" do
post = Post.new :subject => 'foo'
I18n.locale = 'de-DE'
post.subject = 'bar'
I18n.locale = 'he-IL'
post.subject = 'baz'
post.save
I18n.locale = 'en-US'
post = Post.first
assert_equal 'foo', post.subject
I18n.locale = 'de-DE'
assert_equal 'bar', post.subject
I18n.locale = 'he-IL'
assert_equal 'baz', post.subject
end
test "resolves a simple fallback" do
I18n.locale = 'de-DE'
post = Post.create :subject => 'foo'
I18n.locale = 'de'
post.subject = 'baz'
post.content = 'bar'
post.save
I18n.locale = 'de-DE'
assert_equal 'foo', post.subject
assert_equal 'bar', post.content
end
test "resolves a simple fallback without reloading" do
I18n.locale = 'de-DE'
post = Post.new :subject => 'foo'
I18n.locale = 'de'
post.subject = 'baz'
post.content = 'bar'
I18n.locale = 'de-DE'
assert_equal 'foo', post.subject
assert_equal 'bar', post.content
end
test "resolves a complex fallback without reloading" do
I18n.fallbacks.map 'de' => %w(en he)
I18n.locale = 'de'
post = Post.new
I18n.locale = 'en'
post.subject = 'foo'
I18n.locale = 'he'
post.subject = 'baz'
post.content = 'bar'
I18n.locale = 'de'
assert_equal 'foo', post.subject
assert_equal 'bar', post.content
end
test "returns nil if no translations are found" do
post = Post.new :subject => 'foo'
assert_equal 'foo', post.subject
assert_nil post.content
end
test "returns nil if no translations are found; reloaded" do
post = Post.create :subject => 'foo'
post = Post.first
assert_equal 'foo', post.subject
assert_nil post.content
end
test "works with associations" do
blog = Blog.create
post1 = blog.posts.create :subject => 'foo'
I18n.locale = 'de-DE'
post2 = blog.posts.create :subject => 'bar'
assert_equal 2, blog.posts.size
I18n.locale = 'en-US'
assert_equal 'foo', blog.posts.first.subject
assert_nil blog.posts.last.subject
I18n.locale = 'de-DE'
assert_equal 'bar', blog.posts.last.subject
end
test "works with simple dynamic finders" do
foo = Post.create :subject => 'foo'
Post.create :subject => 'bar'
post = Post.find_by_subject('foo')
assert_equal foo, post
end
test 'change attribute on globalized model' do
post = Post.create :subject => 'foo', :content => 'bar'
assert_equal [], post.changed
post.subject = 'baz'
assert_equal [ 'subject' ], post.changed
post.content = 'quux'
assert_member 'subject', post.changed
assert_member 'content', post.changed
end
test 'change attribute on globalized model after locale switching' do
post = Post.create :subject => 'foo', :content => 'bar'
assert_equal [], post.changed
post.subject = 'baz'
I18n.locale = :de
assert_equal [ 'subject' ], post.changed
end
test 'fallbacks with lots of locale switching' do
I18n.fallbacks.map :'de-DE' => [ :'en-US' ]
post = Post.create :subject => 'foo'
I18n.locale = :'de-DE'
assert_equal 'foo', post.subject
I18n.locale = :'en-US'
post.update_attribute :subject, 'bar'
I18n.locale = :'de-DE'
assert_equal 'bar', post.subject
end
test 'reload' do
post = Post.create :subject => 'foo', :content => 'bar'
post.subject = 'baz'
assert_equal 'foo', post.reload.subject
end
test 'complex writing and stashing' do
post = Post.create :subject => 'foo', :content => 'bar'
post.subject = nil
assert_nil post.subject
assert !post.valid?
end
test 'translated class locale setting' do
assert ActiveRecord::Base.respond_to?(:locale)
assert_equal :'en-US', I18n.locale
assert_equal :'en-US', ActiveRecord::Base.locale
I18n.locale = :de
assert_equal :de, I18n.locale
assert_equal :de, ActiveRecord::Base.locale
ActiveRecord::Base.locale = :es
assert_equal :de, I18n.locale
assert_equal :es, ActiveRecord::Base.locale
I18n.locale = :fr
assert_equal :fr, I18n.locale
assert_equal :es, ActiveRecord::Base.locale
end
test "untranslated class responds to locale" do
assert Blog.respond_to?(:locale)
end
test "to ensure locales in different classes are the same" do
ActiveRecord::Base.locale = :de
assert_equal :de, ActiveRecord::Base.locale
assert_equal :de, Parent.locale
Parent.locale = :es
assert_equal :es, ActiveRecord::Base.locale
assert_equal :es, Parent.locale
end
test "attribute saving goes by content locale and not global locale" do
ActiveRecord::Base.locale = :de
assert_equal :'en-US', I18n.locale
Post.create :subject => 'foo'
assert_equal :de, Post.first.globalize_translations.first.locale
end
test "attribute loading goes by content locale and not global locale" do
post = Post.create :subject => 'foo'
assert_equal :'en-US', ActiveRecord::Base.locale
ActiveRecord::Base.locale = :de
assert_equal :'en-US', I18n.locale
post.update_attribute :subject, 'foo [de]'
assert_equal 'foo [de]', Post.first.subject
ActiveRecord::Base.locale = :'en-US'
assert_equal 'foo', Post.first.subject
end
test "access content locale before setting" do
Globalize::Model::ActiveRecord::Translated::ActMethods.class_eval "remove_class_variable(:@@locale)"
assert_nothing_raised { ActiveRecord::Base.locale }
end
test "translated_locales" do
Post.locale = :de
post = Post.create :subject => 'foo'
Post.locale = :es
post.update_attribute :subject, 'bar'
Post.locale = :fr
post.update_attribute :subject, 'baz'
assert_equal [ :de, :es, :fr ], post.translated_locales
assert_equal [ :de, :es, :fr ], Post.first.translated_locales
end
test "including globalize_translations" do
I18n.locale = :de
Post.create :subject => "Foo1", :content => "Bar1"
Post.create :subject => "Foo2", :content => "Bar2"
class << Post
def tranlsations_included
self.all(:include => :globalize_translations)
end
end
default = Post.all.map {|x| [x.subject, x.content]}
with_include = Post.tranlsations_included.map {|x| [x.subject, x.content]}
assert_equal default, with_include
end
test "setting multiple translations at once with options hash" do
Post.locale = :de
post = Post.create :subject => "foo1", :content => "foo1"
Post.locale = :en
post.update_attributes( :subject => "bar1", :content => "bar1" )
options = { :de => {:subject => "foo2", :content => "foo2"},
:en => {:subject => "bar2", :content => "bar2"} }
post.set_translations options
post.reload
assert ["bar2", "bar2"], [post.subject, post.content]
Post.locale = :de
assert ["foo2", "foo2"], [post.subject, post.content]
end
test "setting only one translation with set_translations" do
Post.locale = :de
post = Post.create :subject => "foo1", :content => "foo1"
Post.locale = :en
post.update_attributes( :subject => "bar1", :content => "bar1" )
options = { :en => {:subject => "bar2", :content => "bar2"} }
post.set_translations options
post.reload
assert ["bar2", "bar2"], [post.subject, post.content]
Post.locale = :de
assert ["foo1", "foo1"], [post.subject, post.content]
end
test "setting only selected attributes with set_translations" do
Post.locale = :de
post = Post.create :subject => "foo1", :content => "foo1"
Post.locale = :en
post.update_attributes( :subject => "bar1", :content => "bar1" )
options = { :de => {:content => "foo2"}, :en => {:subject => "bar2"} }
post.set_translations options
post.reload
assert ["bar2", "bar1"], [post.subject, post.content]
Post.locale = :de
assert ["foo1", "foo2"], [post.subject, post.content]
end
test "setting invalid attributes raises ArgumentError" do
Post.locale = :de
post = Post.create :subject => "foo1", :content => "foo1"
Post.locale = :en
post.update_attributes( :subject => "bar1", :content => "bar1" )
options = { :de => {:fake => "foo2"} }
exception = assert_raise(ActiveRecord::UnknownAttributeError) do
post.set_translations options
end
assert_equal "unknown attribute: fake", exception.message
end
test "reload accepting find options" do
p = Post.create :subject => "Foo", :content => "Bar"
assert p.reload(:readonly => true, :lock => true)
assert_raise(ArgumentError) { p.reload(:foo => :bar) }
end
test "dependent destroy of translation" do
p = Post.create :subject => "Foo", :content => "Bar"
assert_equal 1, PostTranslation.count
p.destroy
assert_equal 0, PostTranslation.count
end
test "translating subclass of untranslated comment model" do
translated_comment = TranslatedComment.create(:post => @post)
assert_nothing_raised { translated_comment.globalize_translations }
end
test "modifiying translated comments works as expected" do
I18n.locale = :en
translated_comment = TranslatedComment.create(:post => @post, :content => 'foo')
assert_equal 'foo', translated_comment.content
I18n.locale = :de
translated_comment.content = 'bar'
assert translated_comment.save
assert_equal 'bar', translated_comment.content
I18n.locale = :en
assert_equal 'foo', translated_comment.content
assert_equal 2, translated_comment.globalize_translations.size
end
end
# TODO should validate_presence_of take fallbacks into account? maybe we need
# an extra validation call, or more options for validate_presence_of.
# TODO error checking for fields that exist in main table, don't exist in
# proxy table, aren't strings or text
#
# TODO allow finding by translated attributes in conditions?
# TODO generate advanced dynamic finders?

View file

@ -0,0 +1,26 @@
require 'rubygems'
require 'test/unit'
require 'active_support'
require 'active_support/test_case'
require 'mocha'
$LOAD_PATH << File.expand_path( File.dirname(__FILE__) + '/../lib' )
class ActiveSupport::TestCase
def reset_db!( schema_path )
::ActiveRecord::Migration.verbose = false # Quiet down the migration engine
::ActiveRecord::Base.establish_connection({
:adapter => 'sqlite3',
:dbfile => ':memory:'
})
::ActiveRecord::Base.silence do
load schema_path
end
end
def assert_member(item, arr)
assert_block "Item #{item} is not in array #{arr}" do
arr.member? item
end
end
end

View file

@ -0,0 +1,54 @@
require File.join( File.dirname(__FILE__), 'test_helper' )
require 'globalize/translation'
class TranslationTest < ActiveSupport::TestCase
include Globalize
def setup
@translation = Translation::Static.new 'foo', :locale => :'en-US'
end
test "responds to fallback?" do
assert @translation.respond_to?( :fallback? )
end
test "returns true when :locale and :requested_locale are not equal" do
@translation.requested_locale = :'de-DE'
assert @translation.fallback?
end
test "returns false when :locale and :requested_locale are equal" do
@translation.requested_locale = :'en-US'
assert !@translation.fallback?
end
test "has the attribute :locale" do
assert @translation.respond_to?( :locale )
end
test "has the attribute :requested_locale" do
assert @translation.respond_to?( :requested_locale )
end
test "has the attribute :options" do
assert @translation.respond_to?( :options )
end
test "has the attribute :plural_key" do
assert @translation.respond_to?( :plural_key )
end
test "has the attribute :original" do
assert @translation.respond_to?( :original )
end
test "Translation::Attribute has the attribute :locale" do
translation = Translation::Attribute.new 'foo'
assert translation.respond_to?( :locale )
end
test "Translation::Attribute has the attribute :requested_locale" do
translation = Translation::Attribute.new 'foo'
assert translation.respond_to?( :requested_locale )
end
end