r18n-rails-api 1.0.1 → 1.1.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.
@@ -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