globalize2 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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