globalize2 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. data/.gitignore +2 -1
  2. data/README.textile +27 -143
  3. data/VERSION +1 -1
  4. data/generators/templates/db_backend_migration.rb +3 -3
  5. data/globalize2.gemspec +30 -49
  6. data/init.rb +1 -8
  7. data/lib/globalize.rb +15 -0
  8. data/lib/globalize/active_record.rb +195 -0
  9. data/lib/globalize/active_record/adapter.rb +80 -0
  10. data/lib/globalize/active_record/attributes.rb +25 -0
  11. data/lib/globalize/active_record/migration.rb +40 -0
  12. data/lib/{globalize/i18n → i18n}/missing_translations_log_handler.rb +8 -8
  13. data/lib/{globalize/i18n → i18n}/missing_translations_raise_handler.rb +3 -5
  14. data/test/active_record/fallbacks_test.rb +102 -0
  15. data/test/{model/active_record → active_record}/migration_test.rb +21 -26
  16. data/test/{model/active_record → active_record}/sti_translated_test.rb +4 -30
  17. data/test/active_record/translates_test.rb +87 -0
  18. data/test/active_record/translation_class_test.rb +30 -0
  19. data/test/active_record/validation_tests.rb +75 -0
  20. data/test/active_record_test.rb +451 -0
  21. data/test/data/models.rb +16 -0
  22. data/test/data/schema.rb +23 -7
  23. data/test/i18n/missing_translations_test.rb +6 -6
  24. data/test/test_helper.rb +55 -15
  25. metadata +33 -46
  26. data/lib/globalize/backend/chain.rb +0 -102
  27. data/lib/globalize/backend/pluralizing.rb +0 -37
  28. data/lib/globalize/backend/static.rb +0 -61
  29. data/lib/globalize/load_path.rb +0 -63
  30. data/lib/globalize/locale/fallbacks.rb +0 -63
  31. data/lib/globalize/locale/language_tag.rb +0 -81
  32. data/lib/globalize/model/active_record.rb +0 -56
  33. data/lib/globalize/model/active_record/adapter.rb +0 -100
  34. data/lib/globalize/model/active_record/translated.rb +0 -174
  35. data/lib/globalize/translation.rb +0 -32
  36. data/lib/locale/root.yml +0 -3
  37. data/lib/rails_edge_load_path_patch.rb +0 -40
  38. data/notes.textile +0 -51
  39. data/test/backends/chained_test.rb +0 -175
  40. data/test/backends/pluralizing_test.rb +0 -63
  41. data/test/backends/static_test.rb +0 -147
  42. data/test/data/locale/all.yml +0 -2
  43. data/test/data/locale/de-DE.yml +0 -2
  44. data/test/data/locale/en-US.yml +0 -2
  45. data/test/data/locale/en-US/module.yml +0 -2
  46. data/test/data/locale/fi-FI/module.yml +0 -2
  47. data/test/data/locale/root.yml +0 -0
  48. data/test/load_path_test.rb +0 -49
  49. data/test/locale/fallbacks_test.rb +0 -154
  50. data/test/locale/language_tag_test.rb +0 -130
  51. data/test/model/active_record/translated_test.rb +0 -487
  52. data/test/translation_test.rb +0 -54
@@ -1,32 +0,0 @@
1
- module Globalize
2
- # Translations are simple value objects that carry some context information
3
- # alongside the actual translation string.
4
-
5
- class Translation < String
6
- class Attribute < Translation
7
- attr_accessor :requested_locale, :locale, :key
8
- end
9
-
10
- class Static < Translation
11
- attr_accessor :requested_locale, :locale, :key, :options, :plural_key, :original
12
-
13
- def initialize(string, meta = nil)
14
- self.original = string
15
- super
16
- end
17
- end
18
-
19
- def initialize(string, meta = nil)
20
- set_meta meta
21
- super string
22
- end
23
-
24
- def fallback?
25
- locale.to_sym != requested_locale.to_sym
26
- end
27
-
28
- def set_meta(meta)
29
- meta.each {|name, value| send :"#{name}=", value } if meta
30
- end
31
- end
32
- end
@@ -1,3 +0,0 @@
1
- root:
2
- bidi:
3
- direction: left-to-right
@@ -1,40 +0,0 @@
1
- module I18n
2
- @@load_path = nil
3
- @@default_locale = :'en-US'
4
-
5
- class << self
6
- def load_path
7
- @@load_path ||= []
8
- end
9
-
10
- def load_path=(load_path)
11
- @@load_path = load_path
12
- end
13
- end
14
- end
15
-
16
- I18n::Backend::Simple.module_eval do
17
- def initialized?
18
- @initialized ||= false
19
- end
20
-
21
- protected
22
-
23
- def init_translations
24
- load_translations(*I18n.load_path)
25
- @initialized = true
26
- end
27
-
28
- def lookup(locale, key, scope = [])
29
- return unless key
30
- init_translations unless initialized?
31
- keys = I18n.send :normalize_translation_keys, locale, key, scope
32
- keys.inject(translations){|result, k| result[k.to_sym] or return nil }
33
- end
34
- end
35
-
36
- rails_dir = File.expand_path "#{File.dirname(__FILE__)}/../../../rails/"
37
- paths = %w(actionpack/lib/action_view/locale/en-US.yml
38
- activerecord/lib/active_record/locale/en-US.yml
39
- activesupport/lib/active_support/locale/en-US.yml)
40
- paths.each{|path| I18n.load_path << "#{rails_dir}/#{path}" }
@@ -1,51 +0,0 @@
1
- Stopped DB Backend in the middle, here's where we left off:
2
-
3
- h1. Some Notes
4
-
5
- * Started doing the migration generator in generators/db_backend.rb
6
- * Translation keys will be in dotted string format
7
- * Question: Do we need a plural_key column, or can we build it in to the dotted key?
8
- * We will probably have to code the following methods from scratch, to optimize db calls:
9
- ** translate
10
- ** localize
11
- ** pluralize
12
- * We should refactor @interpolation@ code so that it can be included into backend code without inheriting SimpleBackend
13
- ** Rationale: interpolation is something done entirely after a string is fetched from the data store
14
- ** Alternately, it could be done from within the I18n module
15
-
16
- h1. Schema
17
-
18
- There will be two db tables.
19
-
20
- # globalize_translations will have: locale, key, translation, created_at, updated_at.
21
- # globalize_translations_map will have: key, translation_id.
22
-
23
- globalize_translations_map will let us easily fetch entire sub-trees of namespaces.
24
- However, this table may not be necessary, as it may be feasible to just use key LIKE "some.namespace.%".
25
-
26
- h1. Caching
27
-
28
- We'll almost certainly want to implement caching in the backend. Should probably be a customized
29
- implementation based on the Rails caching mechanism, to support memcached, etc.
30
-
31
- h1. Queries
32
-
33
- We'll want to pull in lots of stuff at once and return a single translation based on some
34
- quick Ruby selection. The query will look something like this:
35
-
36
- <pre>
37
- <code>
38
- SELECT * FROM globalize_translations
39
- WHERE locale in (<fallbacks>) AND
40
- key IN (key, default_key)
41
- </code>
42
- </pre>
43
-
44
- The Ruby code would then pick the first translation that satisfies a fallback, in fallback order.
45
- Of course, the records with the supplied key would take precedence of those with the default key.
46
-
47
- h1. Misc
48
-
49
- We should revisit the :zero plural code. On the one hand it's certainly useful for
50
- many apps in many languages. On the other hand it's not mentioned in CLDR, and not a real
51
- concept in language pluralization. Right now, I'm feeling it's still a good idea to keep it in.
@@ -1,175 +0,0 @@
1
- require File.join( File.dirname(__FILE__), '..', 'test_helper' )
2
- require 'globalize/backend/chain'
3
-
4
- module Globalize
5
- module Backend
6
- class Dummy
7
- def translate(locale, key, options = {})
8
- end
9
- end
10
- end
11
- end
12
-
13
- class ChainedTest < ActiveSupport::TestCase
14
-
15
- test "instantiates a chained backend and sets test as backend" do
16
- assert_nothing_raised { I18n.chain_backends }
17
- assert_instance_of Globalize::Backend::Chain, I18n.backend
18
- end
19
-
20
- test "passes all given arguments to the chained backends #initialize method" do
21
- Globalize::Backend::Chain.expects(:new).with(:spec, :simple)
22
- I18n.chain_backends :spec, :simple
23
- end
24
-
25
- test "passes all given arguments to #add assuming that they are backends" do
26
- # no idea how to spec that
27
- end
28
- end
29
-
30
- class AddChainedTest < ActiveSupport::TestCase
31
- def setup
32
- I18n.backend = Globalize::Backend::Chain.new
33
- end
34
-
35
- test "accepts an instance of a backend" do
36
- assert_nothing_raised { I18n.backend.add Globalize::Backend::Dummy.new }
37
- assert_instance_of Globalize::Backend::Dummy, I18n.backend.send(:backends).first
38
- end
39
-
40
- test "accepts a class and instantiates the backend" do
41
- assert_nothing_raised { I18n.backend.add Globalize::Backend::Dummy }
42
- assert_instance_of Globalize::Backend::Dummy, I18n.backend.send(:backends).first
43
- end
44
-
45
- test "accepts a symbol, constantizes test as a backend class and instantiates the backend" do
46
- assert_nothing_raised { I18n.backend.add :dummy }
47
- assert_instance_of Globalize::Backend::Dummy, I18n.backend.send(:backends).first
48
- end
49
-
50
- test "accepts any number of backend instances, classes or symbols" do
51
- assert_nothing_raised { I18n.backend.add Globalize::Backend::Dummy.new, Globalize::Backend::Dummy, :dummy }
52
- assert_instance_of Globalize::Backend::Dummy, I18n.backend.send(:backends).first
53
- assert_equal [ Globalize::Backend::Dummy, Globalize::Backend::Dummy, Globalize::Backend::Dummy ],
54
- I18n.backend.send(:backends).map{|backend| backend.class }
55
- end
56
-
57
- end
58
-
59
- class TranslateChainedTest < ActiveSupport::TestCase
60
- def setup
61
- I18n.locale = :en
62
- I18n.backend = Globalize::Backend::Chain.new
63
- @first_backend = I18n::Backend::Simple.new
64
- @last_backend = I18n::Backend::Simple.new
65
- I18n.backend.add @first_backend
66
- I18n.backend.add @last_backend
67
- end
68
-
69
- test "delegates #translate to all backends in the order they were added" do
70
- @first_backend.expects(:translate).with(:en, :foo, {})
71
- @last_backend.expects(:translate).with(:en, :foo, {})
72
- I18n.translate :foo
73
- end
74
-
75
- test "returns the result from #translate from the first backend if test's not nil" do
76
- @first_backend.store_translations :en, {:foo => 'foo from first backend'}
77
- @last_backend.store_translations :en, {:foo => 'foo from last backend'}
78
- result = I18n.translate :foo
79
- assert_equal 'foo from first backend', result
80
- end
81
-
82
- test "returns the result from #translate from the second backend if the first one returned nil" do
83
- @first_backend.store_translations :en, {}
84
- @last_backend.store_translations :en, {:foo => 'foo from last backend'}
85
- result = I18n.translate :foo
86
- assert_equal 'foo from last backend', result
87
- end
88
-
89
- test "looks up a namespace from all backends and merges them (if a result is a hash and no count option is present)" do
90
- @first_backend.store_translations :en, {:foo => {:bar => 'bar from first backend'}}
91
- @last_backend.store_translations :en, {:foo => {:baz => 'baz from last backend'}}
92
- result = I18n.translate :foo
93
- assert_equal( {:bar => 'bar from first backend', :baz => 'baz from last backend'}, result )
94
- end
95
-
96
- test "raises a MissingTranslationData exception if no translation was found" do
97
- assert_raise( I18n::MissingTranslationData ) { I18n.translate :not_here, :raise => true }
98
- end
99
-
100
- test "raises an InvalidLocale exception if the locale is nil" do
101
- assert_raise( I18n::InvalidLocale ) { Globalize::Backend::Chain.new.translate nil, :foo }
102
- end
103
-
104
- test "bulk translates a number of keys from different backends" do
105
- @first_backend.store_translations :en, {:foo => 'foo from first backend'}
106
- @last_backend.store_translations :en, {:bar => 'bar from last backend'}
107
- result = I18n.translate [:foo, :bar]
108
- assert_equal( ['foo from first backend', 'bar from last backend'], result )
109
- end
110
-
111
- test "still calls #translate on all the backends" do
112
- @last_backend.expects :translate
113
- I18n.translate :not_here, :default => 'default'
114
- end
115
-
116
- test "returns a given default string when no backend returns a translation" do
117
- result = I18n.translate :not_here, :default => 'default'
118
- assert_equal 'default', result
119
- end
120
-
121
- end
122
-
123
- class CustomLocalizeBackend < I18n::Backend::Simple
124
- def localize(locale, object, format = :default)
125
- "result from custom localize backend" if locale == 'custom'
126
- end
127
- end
128
-
129
- class LocalizeChainedTest < ActiveSupport::TestCase
130
- def setup
131
- I18n.locale = :en
132
- I18n.backend = Globalize::Backend::Chain.new
133
- @first_backend = CustomLocalizeBackend.new
134
- @last_backend = I18n::Backend::Simple.new
135
- I18n.backend.add @first_backend
136
- I18n.backend.add @last_backend
137
- @time = Time.now
138
- end
139
-
140
- test "delegates #localize to all backends in the order they were added" do
141
- @first_backend.expects(:localize).with(:en, @time, :default)
142
- @last_backend.expects(:localize).with(:en, @time, :default)
143
- I18n.localize @time
144
- end
145
-
146
- test "returns the result from #localize from the first backend if test's not nil" do
147
- @last_backend.expects(:localize).never
148
- result = I18n.localize @time, :locale => 'custom'
149
- assert_equal 'result from custom localize backend', result
150
- end
151
-
152
- test "returns the result from #localize from the second backend if the first one returned nil" do
153
- @last_backend.expects(:localize).returns "value from last backend"
154
- result = I18n.localize @time
155
- assert_equal 'value from last backend', result
156
- end
157
- end
158
-
159
- class NamespaceChainedTest < ActiveSupport::TestCase
160
- def setup
161
- @backend = Globalize::Backend::Chain.new
162
- end
163
-
164
- test "returns false if the given result is not a Hash" do
165
- assert !@backend.send(:namespace_lookup?, 'foo', {})
166
- end
167
-
168
- test "returns false if a count option is present" do
169
- assert !@backend.send(:namespace_lookup?, {:foo => 'foo'}, {:count => 1})
170
- end
171
-
172
- test "returns true if the given result is a Hash AND no count option is present" do
173
- assert @backend.send(:namespace_lookup?, {:foo => 'foo'}, {})
174
- end
175
- end
@@ -1,63 +0,0 @@
1
- require File.join( File.dirname(__FILE__), '..', 'test_helper' )
2
- require 'globalize/backend/pluralizing'
3
-
4
- class PluralizingTest < ActiveSupport::TestCase
5
- def setup
6
- @backend = Globalize::Backend::Pluralizing.new
7
- @cz_pluralizer = lambda{|c| c == 1 ? :one : (2..4).include?(c) ? :few : :other }
8
- end
9
-
10
- test "#pluralizer returns the pluralizer for a given locale if defined" do
11
- assert_instance_of Proc, @backend.pluralizer(:en)
12
- end
13
-
14
- test "#pluralizer returns the default pluralizer if no pluralizer is defined for the given locale" do
15
- assert_equal @backend.pluralizer(:en), @backend.pluralizer(:de)
16
- end
17
-
18
- test "#add_pluralizer allows to store a pluralizer per locale" do
19
- assert_nothing_raised { @backend.add_pluralizer(:cz, @cz_pluralizer) }
20
- assert_equal @cz_pluralizer, @backend.pluralizer(:cz)
21
- end
22
-
23
- end
24
-
25
- class PluralizePluralizingTest < ActiveSupport::TestCase
26
- def setup
27
- @backend = Globalize::Backend::Pluralizing.new
28
- @cz_pluralizer = lambda{|c| c == 1 ? :one : (2..4).include?(c) ? :few : :other }
29
- @backend.store_translations :en, :foo => {:one => 'one en foo', :other => 'many en foos'}
30
- @backend.store_translations :cz, :foo => {:one => 'one cz foo', :few => 'few cz foos', :other => 'many cz foos'}
31
- end
32
-
33
- test "looks up the :one translation when count is 1" do
34
- assert_equal 'one en foo', @backend.translate(:en, :foo, :count => 1)
35
- end
36
-
37
- test "looks up the :other translation when count is 2" do
38
- assert_equal 'many en foos', @backend.translate(:en, :foo, :count => 2)
39
- end
40
- end
41
-
42
- class CzPluralizingTest < ActiveSupport::TestCase
43
- def setup
44
- @backend = Globalize::Backend::Pluralizing.new
45
- @cz_pluralizer = lambda{|c| c == 1 ? :one : (2..4).include?(c) ? :few : :other }
46
- @backend.store_translations :en, :foo => {:one => 'one en foo', :other => 'many en foos'}
47
- @backend.store_translations :cz, :foo => {:one => 'one cz foo', :few => 'few cz foos', :other => 'many cz foos'}
48
- @backend.add_pluralizer(:cz, @cz_pluralizer)
49
- end
50
-
51
- test "looks up the :one translation when count is 1 (:cz)" do
52
- assert_equal 'one cz foo', @backend.translate(:cz, :foo, :count => 1)
53
- end
54
-
55
- test "looks up the :few translation when count is 2 (:cz)" do
56
- assert_equal 'few cz foos', @backend.translate(:cz, :foo, :count => 2)
57
- end
58
-
59
- test "looks up the :other translation when count is 5 (:cz)" do
60
- assert_equal 'many cz foos', @backend.translate(:cz, :foo, :count => 5)
61
- end
62
-
63
- end
@@ -1,147 +0,0 @@
1
- require File.join( File.dirname(__FILE__), '..', 'test_helper' )
2
- require 'globalize/backend/static'
3
- require 'globalize/translation'
4
- require 'action_view'
5
- include ActionView::Helpers::NumberHelper
6
-
7
- I18n.locale = :'en-US' # Need to set this, since I18n defaults to 'en'
8
-
9
- class StaticTest < ActiveSupport::TestCase
10
- def setup
11
- I18n.backend = Globalize::Backend::Static.new
12
- translations = { :"en-US" => { :foo => "foo in en-US", :boz => 'boz', :buz => { :bum => 'bum' } },
13
- :"en" => { :bar => "bar in en", :skip_last_comma => "false" },
14
- :"de-DE" => { :baz => "baz in de-DE" },
15
- :"de" => { :boo => "boo in de", :number => { :currency => { :format => { :unit => '€', :format => '%n %u' } } } } }
16
- translations.each do |locale, data|
17
- I18n.backend.store_translations locale, data
18
- end
19
- I18n.fallbacks.map :"de-DE" => :"en-US", :he => :en
20
- end
21
-
22
- test "returns an instance of Translation:Static" do
23
- translation = I18n.translate :foo
24
- assert_instance_of Globalize::Translation::Static, translation
25
- end
26
-
27
- test "returns the translation in en-US if present" do
28
- assert_equal "foo in en-US", I18n.translate(:foo, :locale => :"en-US")
29
- end
30
-
31
- test "returns the translation in en if en-US is not present" do
32
- assert_equal "bar in en", I18n.translate(:bar, :locale => :"en-US")
33
- end
34
-
35
- test "returns the translation in de-DE if present" do
36
- assert_equal "baz in de-DE", I18n.translate(:baz, :locale => :"de-DE")
37
- end
38
-
39
- test "returns the translation in de if de-DE is not present" do
40
- assert_equal "boo in de", I18n.translate(:boo, :locale => :"de-DE")
41
- end
42
-
43
- test "returns the translation in en-US if none of de-DE and de are present" do
44
- assert_equal "foo in en-US", I18n.translate(:foo, :locale => :"de-DE")
45
- end
46
-
47
- test "returns the translation in en if none of de-DE, de and en-US are present" do
48
- assert_equal "bar in en", I18n.translate(:bar, :locale => :"de-DE")
49
- end
50
-
51
- test "returns the translation in en if none in he is present" do
52
- assert_equal "bar in en", I18n.translate(:bar, :locale => :he)
53
- end
54
-
55
- test "returns the given default String when the key is not present for any locale" do
56
- assert_equal "default", I18n.translate(:missing, :default => "default")
57
- end
58
-
59
- test "returns the fallback translation for the key if present for a fallback locale" do
60
- I18n.backend.store_translations :de, :non_default => "non_default in de"
61
- assert_equal "non_default in de", I18n.translate(:non_default, :default => "default", :locale => :"de-DE")
62
- end
63
-
64
- test "returns an array of translations" do
65
- assert_instance_of Array, I18n.translate([:foo, :boz])
66
- end
67
-
68
- test "returns an array of instances of Translation::Static" do
69
- assert_equal [Globalize::Translation::Static], I18n.translate([:foo, :boz]).map(&:class).uniq
70
- end
71
-
72
- test "returns a hash of translations" do
73
- assert_instance_of Hash, I18n.translate(:"buz")
74
- end
75
-
76
- test "returns an array of translations 2" do
77
- assert_equal [Globalize::Translation::Static], I18n.translate(:"buz").values.map(&:class)
78
- end
79
-
80
- test "returns currency properly formated" do
81
- currency = number_to_currency(10)
82
- assert_equal "$10.00", currency
83
- end
84
-
85
- test "returns currency properly formated for locale" do
86
- currency = number_to_currency(10, :locale => :'de')
87
- assert_equal "10.000 €", currency
88
- end
89
-
90
- test "returns currency properly formated from parameters" do
91
- currency = number_to_currency(10, :format => "%n %u", :unit => '€')
92
- assert_equal "10.00 €", currency
93
- end
94
-
95
- # test "makes sure interpolation does not break even with False as string" do
96
- # result = ''
97
- # assert_nothing_raised do
98
- # result = I18n.t(:missing, :default => "{{value}}", :value => false)
99
- # end
100
- # assert_equal "false", result
101
- # end
102
- end
103
-
104
- class TranslationStaticTest < ActiveSupport::TestCase
105
- def setup
106
- I18n.backend = Globalize::Backend::Static.new
107
- translations = {
108
- :greeting => "Hi {{name}}",
109
- :messages => { :one => "You have one message.", :other => "You have {{count}} messages."}
110
- }
111
- I18n.backend.store_translations :"en", translations
112
- end
113
-
114
- def greeting
115
- I18n.translate :greeting, :locale => :"en-US", :name => "Joshua"
116
- end
117
-
118
- test "stores the actual locale" do
119
- assert_equal :en, greeting.locale
120
- end
121
-
122
- test "stores the requested locale" do
123
- assert_equal :'en-US', greeting.requested_locale
124
- end
125
-
126
- test "stores the requested key" do
127
- assert_equal :greeting, greeting.key
128
- end
129
-
130
- test "stores the options given to #translate" do
131
- assert_equal( {:name => "Joshua"}, greeting.options )
132
- end
133
-
134
- test "stores the original translation before test was interpolated" do
135
- assert_equal "Hi {{name}}", greeting.original
136
- end
137
-
138
- test "stores the plural_key :one if pluralized as such" do
139
- message = I18n.translate :messages, :locale => :"en-US", :count => 1
140
- assert_equal :one, message.plural_key
141
- end
142
-
143
- test "stores the plural_key :other if pluralized as such" do
144
- messages = I18n.translate :messages, :locale => :"en-US", :count => 2
145
- assert_equal :other, messages.plural_key
146
- end
147
- end