r18n-rails-api 1.0.1 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -21,6 +21,7 @@ require 'pathname'
21
21
  require 'r18n-core'
22
22
 
23
23
  dir = Pathname(__FILE__).dirname.expand_path + 'r18n-rails-api'
24
+ require dir + 'rails_plural'
24
25
  require dir + 'filters'
25
26
  require dir + 'loader'
26
27
  require dir + 'backend'
@@ -45,7 +45,7 @@ module R18n
45
45
  Array(default).each do |entry|
46
46
  if entry.is_a? Symbol
47
47
  value = lookup(scope, entry, separator, params)
48
- return value if value.translated?
48
+ return value unless value.is_a? Untranslated
49
49
  else
50
50
  return entry
51
51
  end
@@ -85,15 +85,53 @@ module R18n
85
85
 
86
86
  protected
87
87
 
88
+ def format_value(result)
89
+ if result.is_a? TranslatedString
90
+ result.to_s
91
+ elsif result.is_a? UnpluralizetedTranslation
92
+ Utils.hash_map(result.to_hash) do |key, value|
93
+ [RailsPlural.from_r18n(key), value]
94
+ end
95
+ elsif result.is_a? Translation
96
+ translation_to_hash(result)
97
+ else
98
+ result
99
+ end
100
+ end
101
+
102
+ def translation_to_hash(translation)
103
+ Utils.hash_map(translation.to_hash) do |key, value|
104
+ value = if value.is_a? Hash
105
+ translation_to_hash(value)
106
+ else
107
+ format_value(value)
108
+ end
109
+ [key.to_sym, value]
110
+ end
111
+ end
112
+
88
113
  # Find translation by <tt>scope.key(params)</tt> in current R18n I18n
89
114
  # object.
90
115
  def lookup(scope, key, separator, params)
91
116
  keys = (Array(scope) + Array(key)).map { |k|
92
117
  k.to_s.split(separator || ::I18n.default_separator) }.flatten
93
- last = keys.pop
118
+ last = keys.pop.to_sym
119
+
120
+ result = keys.inject(R18n.get.t) do |node, key|
121
+ if node.is_a? TranslatedString
122
+ node.get_untranslated(key)
123
+ else
124
+ node[key]
125
+ end
126
+ end
127
+
128
+ result = if result.is_a? TranslatedString
129
+ result.get_untranslated(key)
130
+ else
131
+ result[last, params]
132
+ end
94
133
 
95
- result = keys.inject(R18n.get) { |result, key| result[key] }
96
- result[last, params]
134
+ format_value(result)
97
135
  end
98
136
  end
99
137
  end
@@ -37,12 +37,30 @@ R18n::Filters.add(String, :named_variables) do |content, config, params|
37
37
  content
38
38
  end
39
39
 
40
+ module R18n
41
+ # Class to mark unpluralized translation and convert Rails plural keys
42
+ class RailsUnpluralizetedTranslation < UnpluralizetedTranslation
43
+ def [](name, *params)
44
+ result = super
45
+ if result.is_a? Untranslated
46
+ fixed = super(RailsPlural.to_r18n(name), *params)
47
+ result = fixed unless fixed.is_a? Untranslated
48
+ end
49
+ result
50
+ end
51
+ end
52
+ end
53
+
40
54
  # Pluralization by named variable <tt>%{count}</tt>.
41
55
  R18n::Filters.add('pl', :named_pluralization) do |content, config, param|
42
56
  if param.is_a? Hash and param.has_key? :count
57
+ hash = content.to_hash
43
58
  type = config[:locale].pluralize(param[:count])
44
- type = 'n' if not content.has_key? type
45
- content[type]
59
+ type = 'n' if not hash.has_key? type
60
+ hash[type]
61
+ elsif content.is_a? R18n::UnpluralizetedTranslation
62
+ R18n::RailsUnpluralizetedTranslation.new(config[:locale], config[:path],
63
+ :locale => config[:locale], :translations => content.to_hash)
46
64
  else
47
65
  content
48
66
  end
@@ -33,17 +33,14 @@ module R18n
33
33
  # R18n::I18n.new('en',
34
34
  # R18n::Loader::Rails.new(I18n::Backend::ActiveRecord.new))
35
35
  class Rails
36
- PLURAL_KEYS = { :zero => 0, :one => 1, :few => 2, :many => 'n',
37
- :other => 'other' }
38
-
39
36
  # Create new loader for some +backend+ from Rails I18n. Backend must have
40
37
  # +reload!+, +init_translations+ and +translations+ methods.
41
38
  def initialize(backend = ::I18n::Backend::Simple.new)
42
39
  @backend = backend
43
- @private_type_class = if ('1.8.' == RUBY_VERSION[0..3] || RUBY_PLATFORM == 'java')
44
- ::YAML::PrivateType
40
+ if ('1.8.' == RUBY_VERSION[0..3] || RUBY_PLATFORM == 'java')
41
+ @private_type_class = ::YAML::PrivateType
45
42
  else
46
- ::Syck::PrivateType
43
+ @private_type_class = ::Syck::PrivateType
47
44
  end
48
45
  end
49
46
 
@@ -85,12 +82,12 @@ module R18n
85
82
  if value.is_a? Hash
86
83
  if value.empty?
87
84
  value
88
- elsif value.keys.inject(true) { |a, i| a and PLURAL_KEYS.include? i }
89
- R18n::Typed.new('pl', R18n::Utils.hash_map(value) { |k, v|
90
- [PLURAL_KEYS[k], transform(v)]
85
+ elsif value.keys.inject(true) { |a, i| a and RailsPlural.is_rails? i }
86
+ Typed.new('pl', R18n::Utils.hash_map(value) { |k, v|
87
+ [RailsPlural.to_r18n(k), transform(v)]
91
88
  })
92
89
  else
93
- R18n::Utils.hash_map(value) { |k, v| [k.to_s, transform(v)] }
90
+ Utils.hash_map(value) { |k, v| [k.to_s, transform(v)] }
94
91
  end
95
92
  elsif value.is_a? @private_type_class
96
93
  Typed.new(value.type_id, value.value)
@@ -0,0 +1,39 @@
1
+ # encoding: utf-8
2
+ =begin
3
+ Converter between R18n and Rails I18n plural keys.
4
+
5
+ Copyright (C) 2009 Andrey “A.I.” Sitnik <andrey@sitnik.ru>
6
+
7
+ This program is free software: you can redistribute it and/or modify
8
+ it under the terms of the GNU Lesser General Public License as published by
9
+ the Free Software Foundation, either version 3 of the License, or
10
+ (at your option) any later version.
11
+
12
+ This program is distributed in the hope that it will be useful,
13
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ GNU Lesser General Public License for more details.
16
+
17
+ You should have received a copy of the GNU Lesser General Public License
18
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
19
+ =end
20
+
21
+ module R18n
22
+ # Converter between R18n and Rails I18n plural keys.
23
+ class RailsPlural
24
+ # Check, that +key+ is Rails plural key.
25
+ def self.is_rails?(k)
26
+ [:zero, :one, :few, :many, :other].include? k
27
+ end
28
+
29
+ # Convert Rails I18n plural key to R18n.
30
+ def self.to_r18n(k)
31
+ { :zero => 0, :one => 1, :few => 2, :many => 'n', :other => 'n' }[k]
32
+ end
33
+
34
+ # Convert R18n plural key to Rails I18n.
35
+ def self.from_r18n(k)
36
+ { 0 => :zero, 1 => :one, 2 => :few, 'n' => :other }[k]
37
+ end
38
+ end
39
+ end
@@ -12,7 +12,7 @@ Gem::Specification.new do |s|
12
12
  R18n has nice Ruby-style syntax, filters, flexible locales, custom loaders,
13
13
  translation support for any classes, time and number localization, several
14
14
  user language support, agnostic core package with out-of-box support for
15
- Rails, Sinatra, Merb and desktop applications.
15
+ Rails, Sinatra and desktop applications.
16
16
  EOF
17
17
 
18
18
  s.files = `git ls-files`.split("\n")
@@ -32,9 +32,9 @@ describe R18n::Backend do
32
32
  end
33
33
 
34
34
  it "should use pluralization and variables" do
35
- I18n.t(:users, :count => 0).should == '0 users'
36
- I18n.t(:users, :count => 1).should == '1 user'
37
- I18n.t(:users, :count => 5).should == '5 users'
35
+ I18n.t('users', :count => 0).should == '0 users'
36
+ I18n.t('users', :count => 1).should == '1 user'
37
+ I18n.t('users', :count => 5).should == '5 users'
38
38
  end
39
39
 
40
40
  it "should use another separator" do
@@ -68,4 +68,44 @@ describe R18n::Backend do
68
68
  I18n.t(:other).should == 'Other'
69
69
  end
70
70
 
71
+ it "should return plain classes" do
72
+ I18n.t('in.another.level').class.should == ActiveSupport::SafeBuffer
73
+ I18n.t('in.another').class.should == Hash
74
+ end
75
+
76
+ it "should return correct unpluralized hash" do
77
+ I18n.t('users').should == { :one => '1 user', :other => '%{count} users' }
78
+ end
79
+
80
+ it "should correct detect untranslated, whem path is deeper than string" do
81
+ lambda {
82
+ I18n.t('in.another.level.deeper')
83
+ }.should raise_error(::I18n::MissingTranslationData)
84
+
85
+ lambda {
86
+ I18n.t('in.another.level.go.deeper')
87
+ }.should raise_error(::I18n::MissingTranslationData)
88
+ end
89
+
90
+ it "should not call String methods" do
91
+ I18n.t('in.another').class.should == Hash
92
+ end
93
+
94
+ it "should not call object methods" do
95
+ lambda {
96
+ I18n.t('in.another.level.to_sym')
97
+ }.should raise_error(::I18n::MissingTranslationData)
98
+ end
99
+
100
+ it "should work deeper pluralization" do
101
+ I18n.t('users.other', :count => 5).should == '5 users'
102
+ end
103
+
104
+ it "should return hash with symbols keys" do
105
+ I18n.t('in').should == {
106
+ :another => { :level => 'Hierarchical' },
107
+ :default => 'Default'
108
+ }
109
+ end
110
+
71
111
  end
@@ -18,4 +18,4 @@ en:
18
18
 
19
19
  users:
20
20
  one: 1 user
21
- many: "%{count} users"
21
+ other: "%{count} users"
@@ -0,0 +1,6 @@
1
+ ru:
2
+ users:
3
+ zero: Ноль
4
+ one: Один
5
+ few: Несколько
6
+ many: Много
@@ -3,5 +3,4 @@ en:
3
3
  zero: Zero
4
4
  one: One
5
5
  few: Few
6
- many: Many
7
6
  other: Other
@@ -2,7 +2,7 @@
2
2
  require File.expand_path('../spec_helper', __FILE__)
3
3
 
4
4
  describe R18n::Loader::Rails do
5
- before :all do
5
+ before do
6
6
  I18n.load_path = [SIMPLE]
7
7
  @loader = R18n::Loader::Rails.new
8
8
  end
@@ -18,7 +18,16 @@ describe R18n::Loader::Rails do
18
18
  it "should change pluralization" do
19
19
  @loader.load(EN).should == {
20
20
  'users' => R18n::Typed.new('pl', {
21
- 0 => 'Zero', 1 => 'One', 2 => 'Few', 'n' => 'Many', 'other' => 'Other'
21
+ 0 => 'Zero', 1 => 'One', 2 => 'Few', 'n' => 'Other'
22
+ })
23
+ }
24
+ end
25
+
26
+ it "should change Russian pluralization" do
27
+ I18n.load_path = [PL]
28
+ @loader.load(RU).should == {
29
+ 'users' => R18n::Typed.new('pl', {
30
+ 0 => 'Ноль', 1 => 'Один', 2 => 'Несколько', 'n' => 'Много'
22
31
  })
23
32
  }
24
33
  end
@@ -11,3 +11,4 @@ RU = R18n.locale(:ru)
11
11
  GENERAL = Dir.glob(File.join(File.dirname(__FILE__), 'data/general/*'))
12
12
  SIMPLE = Dir.glob(File.join(File.dirname(__FILE__), 'data/simple/*'))
13
13
  OTHER = Dir.glob(File.join(File.dirname(__FILE__), 'data/other/*'))
14
+ PL = Dir.glob(File.join(File.dirname(__FILE__), 'data/pl/*'))
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: r18n-rails-api
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.1
4
+ version: 1.1.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-06-30 00:00:00.000000000 Z
12
+ date: 2012-07-15 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: r18n-core
@@ -18,7 +18,7 @@ dependencies:
18
18
  requirements:
19
19
  - - '='
20
20
  - !ruby/object:Gem::Version
21
- version: 1.0.1
21
+ version: 1.1.0
22
22
  type: :runtime
23
23
  prerelease: false
24
24
  version_requirements: !ruby/object:Gem::Requirement
@@ -26,7 +26,7 @@ dependencies:
26
26
  requirements:
27
27
  - - '='
28
28
  - !ruby/object:Gem::Version
29
- version: 1.0.1
29
+ version: 1.1.0
30
30
  - !ruby/object:Gem::Dependency
31
31
  name: i18n
32
32
  requirement: !ruby/object:Gem::Requirement
@@ -165,7 +165,7 @@ description: ! " R18n backend for Rails I18n and R18n filters and loader to s
165
165
  Rails\n translation format.\n R18n has nice Ruby-style syntax, filters, flexible
166
166
  locales, custom loaders,\n translation support for any classes, time and number
167
167
  localization, several\n user language support, agnostic core package with out-of-box
168
- support for\n Rails, Sinatra, Merb and desktop applications.\n"
168
+ support for\n Rails, Sinatra and desktop applications.\n"
169
169
  email: andrey@sitnik.ru
170
170
  executables: []
171
171
  extensions: []
@@ -182,11 +182,13 @@ files:
182
182
  - lib/r18n-rails-api/backend.rb
183
183
  - lib/r18n-rails-api/filters.rb
184
184
  - lib/r18n-rails-api/loader.rb
185
+ - lib/r18n-rails-api/rails_plural.rb
185
186
  - r18n-rails-api.gemspec
186
187
  - spec/backend_spec.rb
187
188
  - spec/data/general/en.yml
188
189
  - spec/data/other/en.yml
189
190
  - spec/data/other/ru.yml
191
+ - spec/data/pl/ru.yml
190
192
  - spec/data/simple/en.yml
191
193
  - spec/data/simple/ru.rb
192
194
  - spec/data/simple/russian.yml
@@ -207,7 +209,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
207
209
  version: '0'
208
210
  segments:
209
211
  - 0
210
- hash: -3012698010051286464
212
+ hash: 3135207149384542194
211
213
  required_rubygems_version: !ruby/object:Gem::Requirement
212
214
  none: false
213
215
  requirements:
@@ -216,7 +218,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
216
218
  version: '0'
217
219
  segments:
218
220
  - 0
219
- hash: -3012698010051286464
221
+ hash: 3135207149384542194
220
222
  requirements: []
221
223
  rubyforge_project:
222
224
  rubygems_version: 1.8.23