i18n-inflector-rails 0.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.
- data.tar.gz.sig +2 -0
- data/.rspec +1 -0
- data/.yardopts +10 -0
- data/ChangeLog +185 -0
- data/Gemfile +17 -0
- data/LGPL-LICENSE +169 -0
- data/Manifest.txt +23 -0
- data/README.rdoc +154 -0
- data/Rakefile +81 -0
- data/docs/COPYING +57 -0
- data/docs/HISTORY +13 -0
- data/docs/LEGAL +11 -0
- data/docs/LGPL-LICENSE +166 -0
- data/docs/TODO +3 -0
- data/docs/rdoc.css +20 -0
- data/i18n-inflector-rails.gemspec +35 -0
- data/init.rb +1 -0
- data/lib/i18n-inflector-rails.rb +25 -0
- data/lib/i18n-inflector-rails/errors.rb +23 -0
- data/lib/i18n-inflector-rails/inflector.rb +185 -0
- data/lib/i18n-inflector-rails/railtie.rb +27 -0
- data/lib/i18n-inflector-rails/version.rb +30 -0
- data/spec/inflector_spec.rb +201 -0
- data/spec/spec_helper.rb +2 -0
- metadata +260 -0
- metadata.gz.sig +0 -0
@@ -0,0 +1,185 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
#
|
3
|
+
# Author:: Paweł Wilk (mailto:pw@gnu.org)
|
4
|
+
# Copyright:: (c) 2011 by Paweł Wilk
|
5
|
+
# License:: This program is licensed under the terms of {file:LGPL-LICENSE GNU Lesser General Public License} or {file:COPYING Ruby License}.
|
6
|
+
#
|
7
|
+
# This file contains I18n::Backend::Inflector::Rails module,
|
8
|
+
# which extends ActionView::Helpers::TranslationHelper
|
9
|
+
# by adding the ability to interpolate patterns containing
|
10
|
+
# inflection tokens defined in translation data.
|
11
|
+
|
12
|
+
module I18n
|
13
|
+
module Inflector
|
14
|
+
module Rails
|
15
|
+
|
16
|
+
# This module contains instance methods for ActionController.
|
17
|
+
module InstanceMethods
|
18
|
+
|
19
|
+
# This method calls the class method {I18n::Inflector::Rails::ClassMethods#i18n_inflector_methods}
|
20
|
+
def i18n_inflector_methods
|
21
|
+
self.class.i18n_inflector_methods
|
22
|
+
end
|
23
|
+
|
24
|
+
# @private
|
25
|
+
def self.included(base)
|
26
|
+
base.helper_method(:i18n_inflector_methods)
|
27
|
+
end
|
28
|
+
|
29
|
+
end # instance methods
|
30
|
+
|
31
|
+
# This module contains class methods for ActionController.
|
32
|
+
module ClassMethods
|
33
|
+
|
34
|
+
# This method reads the internal Hash +i18n_inflector_methods+ containing registered
|
35
|
+
# inflection methods and the assigned kinds. It also reads any methods
|
36
|
+
# assignments that were defined earlier in the inheritance path and
|
37
|
+
# merges them with current results; the most current entries will
|
38
|
+
# override the entries defined before.
|
39
|
+
#
|
40
|
+
# @api public
|
41
|
+
# @return [Hash] the Hash containing assignments made by using {inflection_method}
|
42
|
+
def i18n_inflector_methods
|
43
|
+
prev = superclass.respond_to?(:i18n_inflector_methods) ? superclass.i18n_inflector_methods : {}
|
44
|
+
return @i18n_inflector_methods.nil? ? prev : prev.merge(@i18n_inflector_methods)
|
45
|
+
end
|
46
|
+
|
47
|
+
# This method allows to assign methods (typically attribute readers)
|
48
|
+
# to inflection kinds that are defined in translation files and
|
49
|
+
# supported by {I18n::Inflector} module. Methods registered like that
|
50
|
+
# will be tracked when {translate} is used and their returning values will be
|
51
|
+
# passed as inflection options along with assigned kinds. If the kind is not
|
52
|
+
# given then method assumes that the name of a kind is the same as the given
|
53
|
+
# name of a method.
|
54
|
+
#
|
55
|
+
# @api public
|
56
|
+
# @note Any added method will become helper!
|
57
|
+
# @raise [I18n::Inflector::Rails::BadInflectionMethod] when name or value is malformed
|
58
|
+
# @param [Hash,Array,Symbol,String] assignment the methods and inflection kinds assigned to them
|
59
|
+
# @return [void]
|
60
|
+
# @yield [method, kind, value, caller] optional block that will be executed
|
61
|
+
# each time the registered method is called. Its result will replace
|
62
|
+
# the original returning value of the method that is assigned to a kind
|
63
|
+
# @yieldparam [Symbol] method the name of an assigned method
|
64
|
+
# @yieldparam [Symbol] kind the name of an inflection kind assigned to that +method+
|
65
|
+
# @yieldparam [Object] value the original result of calling the +method+ that will be assigned to a +kind+ as a token
|
66
|
+
# @yieldparam [Object] caller the object that made a call to {translate} method
|
67
|
+
# @yieldreturn [String] the new +value+ (token name) that will be assigned to a +kind+
|
68
|
+
def inflection_method(assignment, &block)
|
69
|
+
if assignment.is_a?(Array)
|
70
|
+
new_assignment = {}
|
71
|
+
assignment.flatten.each{|e| new_assignment[e]=new_assignment}
|
72
|
+
assignment = new_assignment
|
73
|
+
elsif (assignment.is_a?(String) || assignment.is_a?(Symbol))
|
74
|
+
assignment = { assignment => assignment }
|
75
|
+
end
|
76
|
+
|
77
|
+
if (assignment.nil? || !assignment.is_a?(Hash) || assignment.empty?)
|
78
|
+
raise I18n::Inflector::Rails::BadInflectionMethod.new(assignment)
|
79
|
+
end
|
80
|
+
|
81
|
+
@i18n_inflector_methods ||= {}
|
82
|
+
assignment.each_pair do |k,v|
|
83
|
+
k = k.to_s
|
84
|
+
v = v.to_s
|
85
|
+
if (k.empty? || v.empty?)
|
86
|
+
raise I18n::Inflector::Rails::BadInflectionMethod.new("#{k.inspect} => #{v.inspect}")
|
87
|
+
end
|
88
|
+
k = k.to_sym
|
89
|
+
helper_method(k)
|
90
|
+
@i18n_inflector_methods[k] ||= {}
|
91
|
+
@i18n_inflector_methods[k][:kind] = v.to_sym
|
92
|
+
@i18n_inflector_methods[k][:proc] = block
|
93
|
+
end
|
94
|
+
end
|
95
|
+
alias_method :inflection_methods, :inflection_method
|
96
|
+
|
97
|
+
# This method allows to remove methods from sets
|
98
|
+
# created using {inflection_method}. It is useful
|
99
|
+
# when there is a need to break inheritance in some controller,
|
100
|
+
# but a method has been marked as inflection method by
|
101
|
+
# a parrent class.
|
102
|
+
#
|
103
|
+
# @api public
|
104
|
+
# @raise [I18n::Inflector::Rails::BadInflectionMethod] when name or value is malformed
|
105
|
+
# @param [Array] names the method names that should be marked as removed in this controller
|
106
|
+
# @return [void]
|
107
|
+
def no_inflection_method(*names)
|
108
|
+
names = names.flatten
|
109
|
+
if (names.nil? || names.empty?)
|
110
|
+
raise I18n::Inflector::Rails::BadInflectionMethod.new(names)
|
111
|
+
end
|
112
|
+
@i18n_inflector_methods ||= {}
|
113
|
+
names.each do |meth|
|
114
|
+
unless (meth.is_a?(Symbol) || meth.is_a?(String))
|
115
|
+
raise I18n::Inflector::Rails::BadInflectionMethod.new(meth)
|
116
|
+
end
|
117
|
+
meth = meth.to_s
|
118
|
+
raise I18n::Inflector::Rails::BadInflectionMethod.new(meth) if meth.empty?
|
119
|
+
@i18n_inflector_methods[meth.to_sym] = nil
|
120
|
+
end
|
121
|
+
end
|
122
|
+
alias_method :no_inflection_methods, :no_inflection_method
|
123
|
+
|
124
|
+
end # class methods
|
125
|
+
|
126
|
+
# This module contains a version of {translate} method that
|
127
|
+
# tries to use +i18n_inflector_methods+ available in the current context.
|
128
|
+
# The method from this module will wrap the
|
129
|
+
# {ActionView::Helpers::TranslationHelper#translate} method.
|
130
|
+
module InflectedTranslate
|
131
|
+
|
132
|
+
# This method tries to feed itself with the data coming
|
133
|
+
# from +i18n_inflector_methods+ available in the current context.
|
134
|
+
# The data from the last method should contain options
|
135
|
+
# of inflection pairs (<tt>kind => value</tt>) that will
|
136
|
+
# be passed to {I18n::Backend::Inflector#translate} through
|
137
|
+
# {ActionView::Helpers::TranslationHelper#translate}.
|
138
|
+
#
|
139
|
+
# @api public
|
140
|
+
# @param [String] key translation key
|
141
|
+
# @param [Hash] options a set of options to pass to the
|
142
|
+
# translation routines
|
143
|
+
# @return [String] the translated string with inflection patterns
|
144
|
+
# interpolated
|
145
|
+
def translate(*args)
|
146
|
+
test_locale = args.last.is_a?(Hash) ? args.last[:locale] : nil
|
147
|
+
test_locale ||= I18n.locale
|
148
|
+
return super unless I18n.backend.inflector.inflected_locale?(test_locale)
|
149
|
+
|
150
|
+
# collect inflection variables that are present in this context
|
151
|
+
subopts = t_prepare_inflection_options
|
152
|
+
|
153
|
+
# jump to original translate if no variables are present
|
154
|
+
return super if subopts.empty?
|
155
|
+
|
156
|
+
options = args.last.is_a?(Hash) ? args.pop : {}
|
157
|
+
args.push subopts.merge(options)
|
158
|
+
super
|
159
|
+
end
|
160
|
+
|
161
|
+
alias_method :t, :translate
|
162
|
+
|
163
|
+
protected
|
164
|
+
|
165
|
+
# This method tries to read +i18n_inflector_methods+ available in the current context.
|
166
|
+
#
|
167
|
+
# @return [Hash] the inflection options (<tt>kind => value</tt>)
|
168
|
+
def t_prepare_inflection_options
|
169
|
+
subopts = {}
|
170
|
+
i18n_inflector_methods.each_pair do |m, obj|
|
171
|
+
next if obj.nil?
|
172
|
+
value = method(m).call
|
173
|
+
proca = obj[:proc]
|
174
|
+
kind = obj[:kind]
|
175
|
+
value = proca.call(m, kind, value, self) unless proca.nil?
|
176
|
+
subopts[kind] = value.to_s
|
177
|
+
end
|
178
|
+
return subopts
|
179
|
+
end
|
180
|
+
|
181
|
+
end # Translate
|
182
|
+
|
183
|
+
end
|
184
|
+
end
|
185
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
#
|
3
|
+
# Author:: Paweł Wilk (mailto:pw@gnu.org)
|
4
|
+
# Copyright:: (c) 2011 by Paweł Wilk
|
5
|
+
# License:: This program is licensed under the terms of {file:LGPL-LICENSE GNU Lesser General Public License} or {file:COPYING Ruby License}.
|
6
|
+
#
|
7
|
+
# This file loads I18n::Inflector::Rails goodies into Rails.
|
8
|
+
|
9
|
+
module I18n
|
10
|
+
module Inflector
|
11
|
+
module Rails
|
12
|
+
|
13
|
+
class Railtie < ::Rails::Engine
|
14
|
+
|
15
|
+
initializer :before_initialize do
|
16
|
+
ActionController::Base.send(:extend, I18n::Inflector::Rails::ClassMethods)
|
17
|
+
ActionController::Base.send(:include, I18n::Inflector::Rails::InstanceMethods)
|
18
|
+
end
|
19
|
+
|
20
|
+
initializer :after_initialize do
|
21
|
+
ActionController::Base.helper I18n::Inflector::Rails::InflectedTranslate
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
#
|
3
|
+
# Author:: Paweł Wilk (mailto:pw@gnu.org)
|
4
|
+
# Copyright:: (c) 2011 by Paweł Wilk
|
5
|
+
# License:: This program is licensed under the terms of {file:LGPL-LICENSE GNU Lesser General Public License} or {file:COPYING Ruby License}.
|
6
|
+
#
|
7
|
+
# This file contains version information.
|
8
|
+
|
9
|
+
module I18n
|
10
|
+
module Inflector
|
11
|
+
module Rails
|
12
|
+
|
13
|
+
# @private
|
14
|
+
DEVELOPER = 'Paweł Wilk'
|
15
|
+
# @private
|
16
|
+
EMAIL = 'pw@gnu.org'
|
17
|
+
# @private
|
18
|
+
VERSION = '0.1.0'
|
19
|
+
# @private
|
20
|
+
NAME = 'i18n-inflector-rails'
|
21
|
+
# @private
|
22
|
+
SUMMARY = 'I18n Inflector bindings for Rails'
|
23
|
+
# @private
|
24
|
+
URL = 'https://rubygems.org/gems/i18n-inflector-rails/'
|
25
|
+
# @private
|
26
|
+
DESCRIPTION = 'This plug-in provides I18n Inflector module bindings for Rails.'
|
27
|
+
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,201 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
class ApplicationController < ActionController::Base; end
|
4
|
+
class InflectedTranslateController < ApplicationController; end
|
5
|
+
|
6
|
+
describe ApplicationController do
|
7
|
+
|
8
|
+
before do
|
9
|
+
|
10
|
+
I18n.locale = :xx
|
11
|
+
I18n.backend.store_translations(:xx, :i18n => { :inflections => {
|
12
|
+
:gender => {
|
13
|
+
:m => 'male',
|
14
|
+
:f => 'female',
|
15
|
+
:n => 'neuter',
|
16
|
+
:s => 'strange',
|
17
|
+
:masculine => '@m',
|
18
|
+
:feminine => '@f',
|
19
|
+
:neuter => '@n',
|
20
|
+
:neutral => '@neuter',
|
21
|
+
:default => 'neutral' },
|
22
|
+
:person => {
|
23
|
+
:i => 'I',
|
24
|
+
:you => 'You',
|
25
|
+
:it => 'It'}
|
26
|
+
} })
|
27
|
+
I18n.backend.store_translations(:xx, 'welcome' => 'Dear @{f:Lady|m:Sir|n:You|All}!')
|
28
|
+
I18n.backend.store_translations(:xx, 'to_be' => 'Oh @{i:I am|you:You are|it:It is}')
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
describe ".inflection_method" do
|
33
|
+
|
34
|
+
before do
|
35
|
+
class AnotherController < InflectedTranslateController; end
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should be albe to assign a mehtod to the inflection kind" do
|
39
|
+
lambda{AnotherController.inflection_method(:users_gender => :gender)}.should_not raise_error
|
40
|
+
end
|
41
|
+
|
42
|
+
it "should be albe to accept single Symbol argument" do
|
43
|
+
lambda{AnotherController.inflection_method(:time)}.should_not raise_error
|
44
|
+
end
|
45
|
+
|
46
|
+
it "should be albe to accept single String argument" do
|
47
|
+
lambda{AnotherController.inflection_method('time')}.should_not raise_error
|
48
|
+
end
|
49
|
+
|
50
|
+
it "should be albe to accept Array<Symbol> argument" do
|
51
|
+
lambda{AnotherController.inflection_method([:time])}.should_not raise_error
|
52
|
+
end
|
53
|
+
|
54
|
+
it "should be albe to assign a mehtod to the inflection kind with proc" do
|
55
|
+
lambda{AnotherController.inflection_method(:users_gender => :gender){|a,b,c,d,e| :m} }.should_not raise_error
|
56
|
+
lambda{AnotherController.inflection_method(:time){|a,b,c,d,e| :m} }.should_not raise_error
|
57
|
+
end
|
58
|
+
|
59
|
+
it "should raise an error when method name is wrong" do
|
60
|
+
lambda{AnotherController.inflection_method}.should raise_error
|
61
|
+
lambda{AnotherController.inflection_method(nil => :blabla)}.should raise_error
|
62
|
+
lambda{AnotherController.inflection_method(:blabla => nil)}.should raise_error
|
63
|
+
lambda{AnotherController.inflection_method({''=>''})}.should raise_error
|
64
|
+
lambda{AnotherController.inflection_method(nil => nil)}.should raise_error
|
65
|
+
lambda{AnotherController.inflection_method(nil)}.should raise_error
|
66
|
+
lambda{AnotherController.inflection_method([nil])}.should raise_error
|
67
|
+
lambda{AnotherController.inflection_method([''])}.should raise_error
|
68
|
+
lambda{AnotherController.inflection_method([])}.should raise_error
|
69
|
+
lambda{AnotherController.inflection_method({})}.should raise_error
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
73
|
+
|
74
|
+
describe ".no_inflection_method" do
|
75
|
+
|
76
|
+
before do
|
77
|
+
class AnotherController < InflectedTranslateController; end
|
78
|
+
end
|
79
|
+
|
80
|
+
it "should be albe to spit a mehtod of the inflection kind" do
|
81
|
+
lambda{AnotherController.no_inflection_method(:users_gender)}.should_not raise_error
|
82
|
+
end
|
83
|
+
|
84
|
+
it "should be albe to accept single Symbol argument" do
|
85
|
+
lambda{AnotherController.no_inflection_method(:time)}.should_not raise_error
|
86
|
+
end
|
87
|
+
|
88
|
+
it "should be albe to accept single String argument" do
|
89
|
+
lambda{AnotherController.no_inflection_method('time')}.should_not raise_error
|
90
|
+
end
|
91
|
+
|
92
|
+
it "should be albe to accept Array<Symbol> argument" do
|
93
|
+
lambda{AnotherController.no_inflection_method([:time])}.should_not raise_error
|
94
|
+
end
|
95
|
+
|
96
|
+
it "should raise an error when method name is wrong" do
|
97
|
+
lambda{AnotherController.no_inflection_method}.should raise_error
|
98
|
+
lambda{AnotherController.no_inflection_method(nil)}.should raise_error
|
99
|
+
lambda{AnotherController.no_inflection_method([nil])}.should raise_error
|
100
|
+
lambda{AnotherController.no_inflection_method([''])}.should raise_error
|
101
|
+
lambda{AnotherController.no_inflection_method([])}.should raise_error
|
102
|
+
lambda{AnotherController.no_inflection_method({})}.should raise_error
|
103
|
+
end
|
104
|
+
|
105
|
+
end
|
106
|
+
|
107
|
+
describe ".i18n_inflector_methods" do
|
108
|
+
|
109
|
+
before do
|
110
|
+
InflectedTranslateController.inflection_method(:users_gender => :gender)
|
111
|
+
InflectedTranslateController.inflection_method(:time)
|
112
|
+
@expected_hash = {:users_gender=>{:kind=>:gender, :proc=>nil},
|
113
|
+
:time=>{:kind=>:time, :proc=>nil}}
|
114
|
+
end
|
115
|
+
|
116
|
+
it "should be callable" do
|
117
|
+
lambda{InflectedTranslateController.i18n_inflector_methods}.should_not raise_error
|
118
|
+
end
|
119
|
+
|
120
|
+
it "should be able to read methods assigned to inflection kinds" do
|
121
|
+
InflectedTranslateController.i18n_inflector_methods.should == @expected_hash
|
122
|
+
end
|
123
|
+
|
124
|
+
end
|
125
|
+
|
126
|
+
describe "controller instance methods" do
|
127
|
+
|
128
|
+
before do
|
129
|
+
|
130
|
+
class InflectedTranslateController
|
131
|
+
inflection_method :users_gender => :gender
|
132
|
+
def users_gender; :m end
|
133
|
+
def time; :present end
|
134
|
+
def translated_male; translate('welcome') end
|
135
|
+
def t_male; t('welcome') end
|
136
|
+
end
|
137
|
+
|
138
|
+
class InflectedLambdedController < InflectedTranslateController
|
139
|
+
inflection_method(:person) {:it}
|
140
|
+
def person; :you end
|
141
|
+
def translated_person; translate('to_be') end
|
142
|
+
end
|
143
|
+
|
144
|
+
class InflectedLambdedPrimController < InflectedLambdedController
|
145
|
+
inflection_method :person
|
146
|
+
end
|
147
|
+
|
148
|
+
@controller = InflectedTranslateController.new
|
149
|
+
@person_controller = InflectedLambdedController.new
|
150
|
+
@personprim_controller = InflectedLambdedPrimController.new
|
151
|
+
|
152
|
+
@expected_hash = {:users_gender=>{:kind=>:gender, :proc=>nil},
|
153
|
+
:time=>{:kind=>:time, :proc=>nil}}
|
154
|
+
|
155
|
+
end
|
156
|
+
|
157
|
+
describe "#i18n_inflector_methods" do
|
158
|
+
|
159
|
+
it "should be able to read methods assigned to inflection kinds" do
|
160
|
+
@controller.i18n_inflector_methods.should == @expected_hash
|
161
|
+
end
|
162
|
+
|
163
|
+
end
|
164
|
+
|
165
|
+
describe "#translate" do
|
166
|
+
|
167
|
+
it "should translate using inflection patterns and pick up the right value" do
|
168
|
+
@controller.translated_male.should == 'Dear Sir!'
|
169
|
+
end
|
170
|
+
|
171
|
+
it "should make use of blocks if assigned to inflection methods" do
|
172
|
+
@person_controller.translated_person.should == 'Oh It is'
|
173
|
+
end
|
174
|
+
|
175
|
+
it "should make use of inherited inflection method assignments" do
|
176
|
+
@person_controller.translated_male.should == 'Dear Sir!'
|
177
|
+
end
|
178
|
+
|
179
|
+
it "should make use of overriden inflection method assignments" do
|
180
|
+
@personprim_controller.translated_person.should == 'Oh You are'
|
181
|
+
end
|
182
|
+
|
183
|
+
it "should make use of disabled inflection method assignments" do
|
184
|
+
InflectedLambdedPrimController.no_inflection_method :person
|
185
|
+
@personprim_controller.translated_person.should == 'Oh '
|
186
|
+
@person_controller.translated_person.should == 'Oh It is'
|
187
|
+
end
|
188
|
+
|
189
|
+
end
|
190
|
+
|
191
|
+
describe "#t" do
|
192
|
+
|
193
|
+
it "should call translate" do
|
194
|
+
@controller.t_male.should == 'Dear Sir!'
|
195
|
+
end
|
196
|
+
|
197
|
+
end
|
198
|
+
|
199
|
+
end
|
200
|
+
|
201
|
+
end
|
data/spec/spec_helper.rb
ADDED