r18n-core 0.3.2 → 0.4

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 (53) hide show
  1. data/ChangeLog +11 -0
  2. data/README.rdoc +225 -53
  3. data/lib/r18n-core/filters.rb +34 -34
  4. data/lib/r18n-core/i18n.rb +110 -46
  5. data/lib/r18n-core/locale.rb +109 -103
  6. data/lib/r18n-core/translated.rb +9 -4
  7. data/lib/r18n-core/translated_string.rb +10 -0
  8. data/lib/r18n-core/translation.rb +55 -99
  9. data/lib/r18n-core/unsupported_locale.rb +1 -13
  10. data/lib/r18n-core/untranslated.rb +18 -16
  11. data/lib/r18n-core/utils.rb +0 -12
  12. data/lib/r18n-core/version.rb +1 -1
  13. data/lib/r18n-core/yaml_loader.rb +67 -0
  14. data/lib/r18n-core.rb +25 -3
  15. data/locales/cs.rb +30 -16
  16. data/locales/de.rb +21 -0
  17. data/locales/en-us.rb +9 -4
  18. data/locales/en.rb +35 -20
  19. data/locales/eo.rb +20 -0
  20. data/locales/es.rb +20 -0
  21. data/locales/fr.rb +24 -9
  22. data/locales/it.rb +21 -9
  23. data/locales/kk.rb +26 -0
  24. data/locales/pl.rb +30 -18
  25. data/locales/pt-br.rb +24 -0
  26. data/locales/ru.rb +30 -12
  27. data/locales/zh.rb +19 -0
  28. data/spec/filters_spec.rb +24 -7
  29. data/spec/i18n_spec.rb +137 -50
  30. data/spec/locale_spec.rb +91 -53
  31. data/spec/locales/cs_spec.rb +9 -7
  32. data/spec/locales/pl_spec.rb +8 -9
  33. data/spec/locales/ru_spec.rb +9 -9
  34. data/spec/r18n_spec.rb +32 -13
  35. data/spec/spec_helper.rb +28 -4
  36. data/spec/translated_spec.rb +1 -1
  37. data/spec/translation_spec.rb +33 -67
  38. data/spec/translations/two/en.yml +0 -1
  39. data/spec/yaml_loader_spec.rb +33 -0
  40. metadata +11 -16
  41. data/locales/cs.yml +0 -26
  42. data/locales/de.yml +0 -26
  43. data/locales/en-us.yml +0 -10
  44. data/locales/en.yml +0 -26
  45. data/locales/eo.yml +0 -26
  46. data/locales/es.yml +0 -26
  47. data/locales/fr.yml +0 -26
  48. data/locales/it.yml +0 -26
  49. data/locales/kk.yml +0 -26
  50. data/locales/pl.yml +0 -26
  51. data/locales/pt-br.yml +0 -26
  52. data/locales/ru.yml +0 -26
  53. data/locales/zh.yml +0 -26
data/locales/it.rb CHANGED
@@ -1,14 +1,26 @@
1
1
  # encoding: utf-8
2
2
  module R18n
3
- module Locales
4
- class It < R18n::Locale
5
- def format_date_full(i18n, date, year = true)
6
- full = super(i18n, date, year)
7
- if ' 1' == full[0..1]
8
- "1º" + full[2..-1]
9
- else
10
- full
11
- end
3
+ class Locales::It < Locale
4
+ set :title => 'Italiano',
5
+
6
+ :wday_names => %w{domenica lunedì martedì mercoledì giovedì venerdì
7
+ sabato},
8
+ :wday_abbrs => %w{dom lun mar mer gio ven sab},
9
+
10
+ :month_names => %w{gennaio febbraio marzo aprile maggio giugno luglio},
11
+ :month_abbrs => %w{gen feb mar apr mag giu lug ago set ott nov dic},
12
+
13
+ :date_format => '%d/%m/%Y',
14
+
15
+ :number_decimal => ",",
16
+ :number_group => " "
17
+
18
+ def format_date_full(date, year = true, *params)
19
+ full = super(date, year)
20
+ if ' 1' == full[0..1]
21
+ "1º" + full[2..-1]
22
+ else
23
+ full
12
24
  end
13
25
  end
14
26
  end
data/locales/kk.rb ADDED
@@ -0,0 +1,26 @@
1
+ # encoding: utf-8
2
+ module R18n
3
+ class Locales::Kk < Locale
4
+ set :title => 'Қазақша',
5
+ :sublocales => %w{ru en},
6
+
7
+ :wday_names => %w{Жексенбі Дүйсенбі Сейсенбі Сәрсенбі Бейсенбі Жұма
8
+ Сенбі},
9
+ :wday_abbrs => %w{Жк Дс Сс Ср Бс Жм Сн},
10
+
11
+ :month_names => %w{қаңтар ақпан наурыз сәуір мамыр маусым шілде тамыз
12
+ қырқүйек қазан қараша желтоқсан},
13
+ :month_abbrs => %w{қаң ақп нау сәу мам мау шіл там қыр қаз қар жел},
14
+ :month_standalone => %w{Қаңтар Ақпан Наурыз Сәуір Мамыр Маусым Шілде
15
+ Тамыз Қыркүйек Қазан Қараша Желтоқсан},
16
+
17
+ :time_am => ' ертеңің',
18
+ :time_pm => ' кештің',
19
+ :date_format => '%Y-%m-%d',
20
+ :full_format => '%B %e-і',
21
+ :year_format => '%Y жылы _',
22
+
23
+ :number_decimal => ",",
24
+ :number_group => " "
25
+ end
26
+ end
data/locales/pl.rb CHANGED
@@ -1,22 +1,34 @@
1
+ # encoding: utf-8
1
2
  module R18n
2
- module Locales
3
- class Pl < R18n::Locale
4
- def pluralize(n)
5
- return 0 if n == 0
6
- # 0 - 0
7
- # 1 - 1
8
- # 2..4 - 2
9
- # n
10
-
11
- case n % 10
12
- when 1
13
- n > 10 ? 'n' : 1
14
- when 2..4
15
- n % 100 > 10 && n % 100 < 20 ? 'n' : 2
16
- else
17
- 'n'
18
- end
3
+ class Locales::Pl < R18n::Locale
4
+ set :title => 'Polski',
5
+
6
+ :wday_names => %w{niedziela poniedziałek wtorek środa czwartek piątek
7
+ sobota},
8
+ :wday_abbrs => %w{nd pn wt śr czw pt sob},
9
+
10
+ :month_names => %w{stycznia lutego marca kwietnia maja czerwca lipca
11
+ sierpnia września pażdziernika listopada grudnia},
12
+ :month_abbrs => %w{I II III IV V VI VII VIII IX X XI XII},
13
+ :month_standalone => %w{styczeń luty marzec kwiecień maj czerwiec lipiec
14
+ sierpień wrzesień październik listopad
15
+ grudzień},
16
+
17
+ :date_format => '%d/%m/%Y',
18
+
19
+ :number_decimal => ",",
20
+ :number_group => " "
21
+
22
+ def pluralize(n)
23
+ return 0 if n == 0
24
+ case n % 10
25
+ when 1
26
+ n > 10 ? 'n' : 1
27
+ when 2..4
28
+ n % 100 > 10 && n % 100 < 20 ? 'n' : 2
29
+ else
30
+ 'n'
19
31
  end
20
32
  end
21
33
  end
22
- end
34
+ end
data/locales/pt-br.rb ADDED
@@ -0,0 +1,24 @@
1
+ # encoding: utf-8
2
+ module R18n
3
+ class Locales::PtBr < R18n::Locale
4
+ set :title => 'Português brasileiro',
5
+ :code => 'pt-BR',
6
+
7
+ :wday_names => %w{domingo segunda-feira terça-feira quarta-feira
8
+ quinta-feira sexta-feira sábado},
9
+ :wday_abbrs => %w{dom seg ter qua qui sex sab},
10
+
11
+ :month_names => %w{janeiro fevereiro março abril maio junho julho agosto
12
+ setembro outubro novembro dezembro},
13
+ :month_abbrs => %w{jan fev mar abr mai jun jul ago set out nov dez},
14
+ :month_standalone => %w{Janeiro Fevereiro Março Abril Maio Junho Julho
15
+ Agosto Setembro Outubro Novembro Dezembro},
16
+
17
+ :date_format => '%d/%m/%Y',
18
+ :full_format => '%d de %B',
19
+ :year_format => '_ de %Y',
20
+
21
+ :number_decimal => ",",
22
+ :number_group => "."
23
+ end
24
+ end
data/locales/ru.rb CHANGED
@@ -1,16 +1,34 @@
1
+ # encoding: utf-8
1
2
  module R18n
2
- module Locales
3
- class Ru < R18n::Locale
4
- def pluralize(n)
5
- if 0 == n
6
- 0
7
- elsif 1 == n % 10 and 11 != n % 100
8
- 1
9
- elsif 2 <= n % 10 and 4 >= n % 10 and (10 > n % 100 or 20 <= n % 100)
10
- 2
11
- else
12
- 'n'
13
- end
3
+ class Locales::Ru < Locale
4
+ set :title => 'Русский',
5
+
6
+ :wday_names => %w{Воскресенье Понедельник Вторник Среда Четверг Пятница
7
+ Суббота},
8
+ :wday_abbrs => %w{Вск Пнд Втр Срд Чтв Птн Сбт},
9
+
10
+ :month_names => %w{января февраля марта апреля мая июня июля августа
11
+ сентября октября ноября декабря},
12
+ :month_abbrs => %w{янв фев мар апр май июн июл авг сен окт ноя дек},
13
+ :month_standalone => %w{Январь Февраль Март Апрель Май Июнь Июль Август
14
+ Сентябрь Октябрь Ноябрь Декабрь},
15
+
16
+ :time_am => ' утра',
17
+ :time_pm => ' вечера',
18
+ :date_format => '%d.%m.%Y',
19
+
20
+ :number_decimal => ",",
21
+ :number_group => " "
22
+
23
+ def pluralize(n)
24
+ if 0 == n
25
+ 0
26
+ elsif 1 == n % 10 and 11 != n % 100
27
+ 1
28
+ elsif 2 <= n % 10 and 4 >= n % 10 and (10 > n % 100 or 20 <= n % 100)
29
+ 2
30
+ else
31
+ 'n'
14
32
  end
15
33
  end
16
34
  end
data/locales/zh.rb ADDED
@@ -0,0 +1,19 @@
1
+ # encoding: utf-8
2
+ module R18n
3
+ class Locales::Zh < R18n::Locale
4
+ set :title => '中文',
5
+
6
+ :wday_names => %w{星期日 星期一 星期二 星期三 星期四 星期五 星期六},
7
+ :wday_abbrs => %w{周日 周一 周二 周三 周四 周五 周六},
8
+
9
+ :month_names => %w{一月 二月 三月 四月 五月 六月 七月 八月 九月 十月 十一月 十二月},
10
+ :month_abbrs => %w{一月 二月 三月 四月 五月 六月 七月 八月 九月 十月 十一月 十二月},
11
+
12
+ :date_format => '%Y年%m月%d日',
13
+ :full_format => '%m月%d日',
14
+ :year_format => '%Y年_',
15
+
16
+ :number_decimal => ".",
17
+ :number_group => " "
18
+ end
19
+ end
data/spec/filters_spec.rb CHANGED
@@ -88,21 +88,21 @@ describe R18n::Filters do
88
88
 
89
89
  it "should send config to filter" do
90
90
  R18n::Filters.add('my') do |i, config|
91
- config.secret_value = 1
91
+ config[:secret_value] = 1
92
92
  config
93
93
  end
94
- @i18n.my_filter.locale.should == @i18n.locale
95
- @i18n.my_filter.path.should == 'my_filter'
96
- @i18n.my_filter.secret_value.should == 1
97
- @i18n.my_filter.unknown_value.should be_nil
94
+ @i18n.my_filter[:locale].should == @i18n.locale
95
+ @i18n.my_filter[:path].should == 'my_filter'
96
+ @i18n.my_filter[:secret_value].should == 1
97
+ @i18n.my_filter[:unknown_value].should be_nil
98
98
  end
99
99
 
100
100
  it "should use one config for cascade filters" do
101
- R18n::Filters.add('my') { |content, config| config.new_secret ? 2 : 1 }
101
+ R18n::Filters.add('my') { |content, config| config[:new_secret] ? 2 : 1 }
102
102
  @i18n.my_filter.should == 1
103
103
 
104
104
  R18n::Filters.add('my', nil, 0) do |content, config|
105
- config.new_secret = true
105
+ config[:new_secret] = true
106
106
  content
107
107
  end
108
108
  @i18n.my_filter.should == 2
@@ -127,6 +127,11 @@ describe R18n::Filters do
127
127
  @i18n.files(-5.5).should == '−5.5 files'
128
128
  @i18n.files(5000).should == '5,000 files'
129
129
  end
130
+
131
+ it "shouldn't pluralize without first numeric parameter" do
132
+ @i18n.files.should == { 1 => '1 file', 'n' => '%1 files' }
133
+ @i18n.files('').should == { 1 => '1 file', 'n' => '%1 files' }
134
+ end
130
135
 
131
136
  it "should pluralize translation without locale" do
132
137
  i18n = R18n::I18n.new('no-LC', DIR)
@@ -150,6 +155,18 @@ describe R18n::Filters do
150
155
  @i18n.in.not.to_s.should == 'in.not in.[not]'
151
156
  end
152
157
 
158
+ it "should format translation path" do
159
+ @i18n.in.another.to_s.should == 'in.another[]'
160
+
161
+ R18n::Filters.off(:untranslated)
162
+ @i18n.in.another.to_s.should == 'in.another'
163
+
164
+ R18n::Filters.add(R18n::Untranslated) do |v, c, trans, untrans, path|
165
+ "#{path} #{trans}[#{untrans}]"
166
+ end
167
+ @i18n.in.another.to_s.should == 'in.another in.another[]'
168
+ end
169
+
153
170
  it "should have filter for escape HTML" do
154
171
  @i18n.html.should == '&lt;script&gt;true &amp;&amp; false&lt;/script&gt;'
155
172
  end
data/spec/i18n_spec.rb CHANGED
@@ -2,8 +2,15 @@
2
2
  require File.join(File.dirname(__FILE__), 'spec_helper')
3
3
 
4
4
  describe R18n::I18n do
5
+ before do
6
+ @extension_places = R18n.extension_places.clone
7
+ R18n.cache.clear
8
+ end
9
+
5
10
  after do
6
11
  R18n::I18n.default = 'en'
12
+ R18n.default_loader = R18n::Loader::YAML
13
+ R18n.extension_places = @extension_places
7
14
  end
8
15
 
9
16
  it "should parse HTTP_ACCEPT_LANGUAGE" do
@@ -26,20 +33,68 @@ describe R18n::I18n do
26
33
  i18n.locales.should == [R18n::Locale.load('ru'),
27
34
  R18n::UnsupportedLocale.new('no-LC'),
28
35
  R18n::UnsupportedLocale.new('no'),
29
- R18n::UnsupportedLocale.new('en')]
36
+ R18n::Locale.load('en')]
30
37
  end
31
38
 
32
- it "should return translations dir" do
39
+ it "should return translations loaders" do
33
40
  i18n = R18n::I18n.new('en', DIR)
34
- i18n.translation_dirs.expand_path.to_s.should == DIR.expand_path.to_s
41
+ i18n.translation_places.should == [R18n::Loader::YAML.new(DIR)]
42
+ end
43
+
44
+ it "should load translations by loader" do
45
+ loader = Class.new do
46
+ def available; [R18n::Locale.load('en')]; end
47
+ def load(locale); { 'custom' => 'Custom' }; end
48
+ end
49
+ R18n::I18n.new('en', loader.new).custom.should == 'Custom'
50
+ end
51
+
52
+ it "should pass parameters to default loader" do
53
+ loader = Class.new do
54
+ def initialize(param); @param = param; end
55
+ def available; [R18n::Locale.load('en')]; end
56
+ def load(locale); { 'custom' => @param }; end
57
+ end
58
+ R18n.default_loader = loader
59
+ R18n::I18n.new('en', 'default').custom.should == 'default'
35
60
  end
36
61
 
37
62
  it "should load translations" do
38
63
  i18n = R18n::I18n.new(['ru', 'en'], DIR)
39
64
  i18n.one.should == 'Один'
65
+ i18n[:one].should == 'Один'
40
66
  i18n['one'].should == 'Один'
41
67
  i18n.only.english.should == 'Only in English'
42
68
  end
69
+
70
+ it "should load translations from several dirs" do
71
+ i18n = R18n::I18n.new(['no-LC', 'en'], [TWO, DIR])
72
+ i18n.in.two.should == 'Two'
73
+ i18n.in.another.level.should == 'Hierarchical'
74
+ end
75
+
76
+ it "should use extension places" do
77
+ R18n.extension_places << EXT
78
+
79
+ i18n = R18n::I18n.new('en', DIR)
80
+ i18n.ext.should == 'Extension'
81
+ i18n.one.should == 'One'
82
+ end
83
+
84
+ it "shouldn't use extension without app translations with same locale" do
85
+ R18n.extension_places << EXT
86
+
87
+ i18n = R18n::I18n.new(['no-TR', 'en'], DIR)
88
+ i18n.ext.should == 'Extension'
89
+ end
90
+
91
+ it "should ignore case on loading" do
92
+ i18n = R18n::I18n.new('no-lc', [DIR])
93
+ i18n.one.should == 'ONE'
94
+
95
+ i18n = R18n::I18n.new('no-LC', [DIR])
96
+ i18n.one.should == 'ONE'
97
+ end
43
98
 
44
99
  it "should load default translation" do
45
100
  i18n = R18n::I18n.new('no-LC', DIR)
@@ -56,9 +111,86 @@ describe R18n::I18n do
56
111
  end
57
112
 
58
113
  it "should return available translations" do
114
+ R18n::I18n.available_locales(DIR).should =~ [R18n::Locale.load('no-lc'),
115
+ R18n::Locale.load('ru'),
116
+ R18n::Locale.load('en')]
59
117
  i18n = R18n::I18n.new('en', DIR)
60
- i18n.translations.should == { 'no-lc' => 'no-lc', 'ru' => 'Русский',
61
- 'en' => 'English' }
118
+ i18n.available_locales.should =~ [R18n::Locale.load('no-lc'),
119
+ R18n::Locale.load('ru'),
120
+ R18n::Locale.load('en')]
121
+ end
122
+
123
+ it "should cache translations" do
124
+ counter = CounterLoader.new('en')
125
+
126
+ R18n::I18n.new('en', counter)
127
+ counter.loaded.should == 1
128
+
129
+ R18n::I18n.new('en', counter)
130
+ counter.loaded.should == 1
131
+
132
+ R18n.cache.clear
133
+ R18n::I18n.new('en', counter)
134
+ counter.loaded.should == 2
135
+ end
136
+
137
+ it "should cache translations by used locales" do
138
+ counter = CounterLoader.new('en', 'ru')
139
+
140
+ R18n::I18n.new('en', counter)
141
+ counter.loaded.should == 1
142
+
143
+ R18n::I18n.new(['en', 'fr'], counter)
144
+ counter.loaded.should == 1
145
+
146
+ R18n::I18n.new(['en', 'ru'], counter)
147
+ counter.loaded.should == 3
148
+
149
+ R18n::I18n.new(['ru', 'en'], counter)
150
+ counter.loaded.should == 5
151
+ end
152
+
153
+ it "should cache translations by places" do
154
+ counter = CounterLoader.new('en', 'ru')
155
+
156
+ R18n::I18n.new('en', counter)
157
+ counter.loaded.should == 1
158
+
159
+ R18n::I18n.new('en', [counter, DIR])
160
+ counter.loaded.should == 2
161
+
162
+ R18n.extension_places << EXT
163
+ R18n::I18n.new('en', counter)
164
+ counter.loaded.should == 3
165
+
166
+ same = CounterLoader.new('en', 'ru')
167
+ R18n::I18n.new('en', same)
168
+ same.loaded.should == 0
169
+
170
+ different = CounterLoader.new('en', 'fr')
171
+ R18n::I18n.new('en', different)
172
+ different.loaded.should == 1
173
+ end
174
+
175
+ it "should reload translations" do
176
+ loader = Class.new do
177
+ @@answer = 1
178
+ def available; [R18n::Locale.load('en')]; end
179
+ def load(locale); { 'one' => @@answer }; end
180
+ end
181
+
182
+ i18n = R18n::I18n.new('en', loader.new)
183
+ i18n.one.should == 1
184
+
185
+ loader.class_eval { @@answer = 2 }
186
+ i18n.reload!
187
+ i18n.one.should == 2
188
+ end
189
+
190
+ it "should return translations" do
191
+ i18n = R18n::I18n.new('en', DIR)
192
+ i18n.t.should be_a(R18n::Translation)
193
+ i18n.t.one.should == 'One'
62
194
  end
63
195
 
64
196
  it "should return first locale with locale file" do
@@ -81,50 +213,5 @@ describe R18n::I18n do
81
213
 
82
214
  i18n.l(Date.new(0)).should == '01.01.0000'
83
215
  end
84
-
85
- it "should localize date for human" do
86
- i18n = R18n::I18n.new('ru')
87
-
88
- i18n.l(Date.today + 2, :human).should == 'через 2 дня'
89
- i18n.l(Date.today + 1, :human).should == 'завтра'
90
- i18n.l(Date.today, :human).should == 'сегодня'
91
- i18n.l(Date.today - 1, :human).should == 'вчера'
92
- i18n.l(Date.today - 3, :human).should == '3 дня назад'
93
-
94
- y2000 = Date.parse('2000-01-08')
95
- i18n.l(y2000, :human, Date.parse('2000-01-01')).should == ' 8 января'
96
- i18n.l(y2000, :human, Date.parse('1999-01-01')).should == ' 8 января 2000'
97
- end
98
-
99
- it "should localize times for human" do
100
- i18n = R18n::I18n.new('ru')
101
- minute = 60
102
- hour = 60 * minute
103
- day = 24 * hour
104
- zero = Time.at(0).utc
105
-
106
- i18n.l( zero + 7 * day, :human, zero).should == ' 8 января 00:00'
107
- i18n.l( zero + 50 * hour, :human, zero).should == 'через 2 дня 02:00'
108
- i18n.l( zero + 25 * hour, :human, zero).should == 'завтра 01:00'
109
- i18n.l( zero + 70 * minute, :human, zero).should == 'через 1 час'
110
- i18n.l( zero + 38 * minute, :human, zero).should == 'через 38 минут'
111
- i18n.l( zero + 5, :human, zero).should == 'сейчас'
112
- i18n.l( zero - 15, :human, zero).should == 'сейчас'
113
- i18n.l( zero - minute, :human, zero).should == '1 минуту назад'
114
- i18n.l( zero - 2 * hour, :human, zero).should == '2 часа назад'
115
- i18n.l( zero - 13 * hour, :human, zero).should == 'вчера 11:00'
116
- i18n.l( zero - 50 * hour, :human, zero).should == '3 дня назад 22:00'
117
- i18n.l( zero - 9 * day, :human, zero).should == '23 декабря 1969 00:00'
118
- end
119
-
120
- it "should use standard formatter by default" do
121
- R18n::I18n.new('ru').l(Time.at(0).utc).should == '01.01.1970 00:00'
122
- end
123
-
124
- it "should raise error on unknown formatter" do
125
- lambda {
126
- R18n::I18n.new('ru').l(Time.at(0).utc, :unknown)
127
- }.should raise_error(ArgumentError, /formatter/)
128
- end
129
216
 
130
217
  end