i18n_scopes 0.0.1 → 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.
- data/README.md +12 -7
- data/i18n_scopes.gemspec +1 -1
- data/lib/i18n_scopes.rb +1 -0
- data/lib/i18n_scopes/configuration.rb +42 -53
- data/lib/i18n_scopes/option_accessor.rb +48 -0
- data/lib/i18n_scopes/scope.rb +62 -35
- data/lib/i18n_scopes/translation_helper.rb +137 -133
- data/lib/i18n_scopes/translation_methods.rb +37 -36
- data/lib/i18n_scopes/version.rb +1 -1
- data/spec/configuration_spec.rb +12 -12
- data/spec/example_classes/inherited.rb +13 -0
- data/spec/example_classes/respondable.rb +4 -4
- data/spec/example_classes/scope_t_with_path.rb +16 -11
- data/spec/example_classes/scope_t_with_path_in_module.rb +4 -4
- data/spec/example_classes/should_define_scope.rb +1 -1
- data/spec/example_classes/should_have_attached_scoped_t.rb +1 -1
- data/spec/include_scope_spec.rb +8 -8
- data/spec/inherited_spec.rb +11 -0
- data/spec/locales/en.yml +9 -1
- data/spec/scope_spec.rb +12 -11
- data/spec/should_define_scope_spec.rb +5 -3
- metadata +8 -3
data/README.md
CHANGED
@@ -30,28 +30,33 @@ Or install it yourself as:
|
|
30
30
|
### In your class (for example Controller)
|
31
31
|
|
32
32
|
class Local::ExampleController < ActionController::Base
|
33
|
-
|
33
|
+
i18n_default_scope :class_name, :translation, :action_name, :strip_controller_suffix => true, :plural_class => false
|
34
|
+
i18n_scope :flash, :class_name, :action_name, :flashes
|
34
35
|
|
35
36
|
def index
|
36
37
|
@post = Post.new
|
37
38
|
self.examples
|
38
39
|
end
|
39
40
|
|
41
|
+
protected
|
40
42
|
def examples
|
41
|
-
# the
|
42
|
-
|
43
|
+
# the t_scoped method will inherit the path from the i18n_scope method
|
44
|
+
t_scoped :name # => [:example, :translation, :index, :name]
|
43
45
|
|
44
46
|
# the path can be overwritten with an option
|
45
|
-
|
47
|
+
t_scoped :name, :path => :elsewhere # => [:elsewhere, :name]
|
46
48
|
|
47
49
|
# the path can be extended through the :path_extension options, it'll be attached to the end of path
|
48
|
-
|
50
|
+
t_scoped :name, :path_extension => :flash, # => [:example, :translation, :index, :flash, :name]
|
49
51
|
|
50
52
|
# it's also possible to use local methods as path, in this example :modules_with_extension will be called, note that
|
51
|
-
|
53
|
+
t_scoped :name, :path_extension => :modules_with_extension # => [:example, :translation, :index, :local_modules, :name]
|
52
54
|
|
53
55
|
# in this example, the post object will be given as argument, @post will respond to :post_scope and returns :normal
|
54
|
-
|
56
|
+
t_scoped :name, :path_extension => :post_scope, :respondable => @post # => [:example, :translation, :index, :normal, :name]
|
57
|
+
|
58
|
+
# this will call the named scope +t_flash+ and extend it with a path_extension
|
59
|
+
t_flash :name, :path_extension => :success # => [:example, :index, :flashes, :sucess, :name]
|
55
60
|
end
|
56
61
|
|
57
62
|
def modules_with_extension(modules)
|
data/i18n_scopes.gemspec
CHANGED
@@ -5,7 +5,7 @@ Gem::Specification.new do |gem|
|
|
5
5
|
gem.authors = ["menostos"]
|
6
6
|
gem.email = ["menostos@gmail.com"]
|
7
7
|
gem.description = %q{A gem for adding dynamic scopes to classes}
|
8
|
-
gem.summary = %q{This gem will attach a
|
8
|
+
gem.summary = %q{This gem will attach a t_scoped method to your class. The scope will be configureable in your class or globally.}
|
9
9
|
gem.homepage = "http://github.com/menostos/i18n_scopes"
|
10
10
|
|
11
11
|
gem.files = `git ls-files`.split($\)
|
data/lib/i18n_scopes.rb
CHANGED
@@ -2,58 +2,47 @@
|
|
2
2
|
# see I18nScopes::Configuration
|
3
3
|
module I18nScopes
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
end
|
48
|
-
|
49
|
-
# returns the Configuration as option Hash
|
50
|
-
def as_options
|
51
|
-
{
|
52
|
-
:plural_classes => self.plural_classes,
|
53
|
-
:strip_controller_suffix => self.strip_controller_suffix
|
54
|
-
}
|
55
|
-
end
|
56
|
-
|
57
|
-
end
|
5
|
+
# use this method to configure I18nScopes
|
6
|
+
#
|
7
|
+
# I18nScopes.configure do |config|
|
8
|
+
# config.plural_classes = false
|
9
|
+
# config.strip_controller_suffix = true
|
10
|
+
# config.attach_to ActionController::Base, YourCustomClass, EtcClass
|
11
|
+
# end
|
12
|
+
def self.configure # :yield: config
|
13
|
+
yield self.configuration
|
14
|
+
end
|
15
|
+
|
16
|
+
# returns the Configuration
|
17
|
+
def self.configuration
|
18
|
+
@configuration ||= Configuration.new
|
19
|
+
end
|
20
|
+
|
21
|
+
# this class is used to hold the global configuration made for I18nScopes
|
22
|
+
class Configuration
|
23
|
+
|
24
|
+
include I18nScopes::OptionAccessor
|
25
|
+
|
26
|
+
option_accessor :plural_classes, false
|
27
|
+
option_accessor :strip_controller_suffix, true
|
28
|
+
|
29
|
+
# Attach the I18nScope methods to the given class or classes
|
30
|
+
#
|
31
|
+
# === Params:
|
32
|
+
# * +klasses+:: +Class+ one or more Class the include the I18nScopes methods
|
33
|
+
#
|
34
|
+
# I18nScopes.configuration.attach_to ActionController::Base, YourCustomClass, EtcClass
|
35
|
+
def attach_to(*klasses)
|
36
|
+
klasses.each do |klass|
|
37
|
+
klass.send :include, I18nScopes::Scope
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
# returns the Configuration as option Hash
|
42
|
+
def as_options
|
43
|
+
return self.options
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
58
47
|
|
59
48
|
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module I18nScopes
|
2
|
+
|
3
|
+
# creates an option_accessor class method, to help create an options hash
|
4
|
+
module OptionAccessor
|
5
|
+
|
6
|
+
extend ActiveSupport::Concern
|
7
|
+
|
8
|
+
# accessor for all options
|
9
|
+
def options
|
10
|
+
@options ||= self.create_options
|
11
|
+
end
|
12
|
+
|
13
|
+
protected
|
14
|
+
# create options with all default options in it
|
15
|
+
def create_options
|
16
|
+
options = Hash.new
|
17
|
+
self.class.default_options.each do |option, value|
|
18
|
+
options[option] = value
|
19
|
+
end
|
20
|
+
return options
|
21
|
+
end
|
22
|
+
|
23
|
+
module ClassMethods
|
24
|
+
|
25
|
+
# creates accessor for options
|
26
|
+
# === Params:
|
27
|
+
# * +option+: the option key
|
28
|
+
# * +default+: the default option
|
29
|
+
def option_accessor(option, default = nil)
|
30
|
+
self.default_options[option] = default
|
31
|
+
define_method(option) do
|
32
|
+
self.options[option.to_sym] ||= default
|
33
|
+
end
|
34
|
+
define_method(:"#{option}=") do |value|
|
35
|
+
self.options[option.to_sym] = value
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
# default options
|
40
|
+
def default_options
|
41
|
+
@default_options ||= {}
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
data/lib/i18n_scopes/scope.rb
CHANGED
@@ -1,43 +1,70 @@
|
|
1
1
|
module I18nScopes
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
3
|
+
# This module can be included to get the i18n_scope method on every class
|
4
|
+
#
|
5
|
+
# this can also be achieved using the Configuration#attach_to method from the Configuration
|
6
|
+
#
|
7
|
+
# === Usage:
|
8
|
+
#
|
9
|
+
# class Example
|
10
|
+
# include I18nScopes::Scope
|
11
|
+
# end
|
12
|
+
module Scope
|
13
13
|
|
14
|
-
|
14
|
+
extend ActiveSupport::Concern
|
15
15
|
|
16
|
-
|
16
|
+
module ClassMethods
|
17
17
|
|
18
|
-
|
18
|
+
attr_accessor :i18n_scope_helper
|
19
19
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
20
|
+
# Use this method to configure how the scope will be built when using translations
|
21
|
+
# === Params:
|
22
|
+
# * +path+: Either a single String or Symbol, or an Array of Symbols and Strings
|
23
|
+
# * +options+: options to be used within this class, they will overwrite the configuration made in Configuration
|
24
|
+
# * :plural_class: if the class name should be pluralized or singularized
|
25
|
+
# * :strip_controller_suffix: if the _controller suffix of classes should be stripped or not
|
26
|
+
#
|
27
|
+
# == Usage:
|
28
|
+
# i18n_scope :flash, :modules, :class_name, :action_name, :custom_value, "static_prefix", :plural_class => true, :strip_controller_suffix => true
|
29
|
+
#
|
30
|
+
# this will create a +t_flash+ method
|
31
|
+
#
|
32
|
+
# with a Tweets::PostsController, the action index and a custom_value method that returns a_value this will led to the following scope:
|
33
|
+
#
|
34
|
+
# [:tweets, :posts, :index, :a_value, "static_prefix"]
|
35
|
+
def i18n_scope(name, *path)
|
36
|
+
@i18n_scope_initialized ||= begin
|
37
|
+
self.send :include, I18nScopes::TranslationMethods
|
38
|
+
self.i18n_scope_helper ||= {}
|
39
|
+
true
|
40
|
+
end
|
41
|
+
options = path.extract_options!
|
42
|
+
as = options.delete(:as) || :"t_#{name}"
|
43
|
+
self.i18n_scope_helper[name] = I18nScopes::TranslationHelper.new(path.flatten, options)
|
44
|
+
|
45
|
+
define_method(as) do |*args|
|
46
|
+
i18n_scope_helper = self.class.i18n_scope_helper[name]
|
47
|
+
klass = self.class
|
48
|
+
while(!i18n_scope_helper && klass.superclass != Object)
|
49
|
+
klass = klass.superclass
|
50
|
+
i18n_scope_helper = klass.i18n_scope_helper[name]
|
51
|
+
end
|
52
|
+
scoped_translation(i18n_scope_helper, *args)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
# this method creates a default scope
|
57
|
+
# this is equivalent to calling
|
58
|
+
# i18n_scope :default, :as => :t_scoped
|
59
|
+
def i18n_default_scope(*path)
|
60
|
+
options = path.extract_options!
|
61
|
+
options[:as] ||= :t_scoped
|
62
|
+
path << options
|
63
|
+
i18n_scope(:default, *path)
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
42
69
|
|
43
70
|
end
|
@@ -1,147 +1,151 @@
|
|
1
1
|
module I18nScopes
|
2
2
|
|
3
|
-
|
4
|
-
|
3
|
+
# this class provides helper methods to determine the actual scope in your class
|
4
|
+
class TranslationHelper
|
5
5
|
|
6
|
-
|
6
|
+
CONTROLLER_SUFFIX = "_controller"
|
7
7
|
|
8
|
-
|
9
|
-
|
8
|
+
attr_accessor :path
|
9
|
+
attr_accessor :options
|
10
10
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
11
|
+
# === Params:
|
12
|
+
# * +path+: the path from i18n_scope
|
13
|
+
# * +options+ the options from i18n_scope
|
14
|
+
def initialize(path, options = {})
|
15
|
+
self.path = path
|
16
|
+
self.options = I18nScopes.configuration.as_options.merge(options)
|
17
|
+
end
|
18
18
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
19
|
+
# === Params:
|
20
|
+
# * +object+: the object which is doing a translation
|
21
|
+
# * +options+: additional options for this translation
|
22
|
+
# * +parameter_matchings+: a Hash providing arguments to custom methods
|
23
|
+
def scope_from_path(object, options, parameter_matchings)
|
24
|
+
scope = []
|
25
|
+
custom_path = if options.include?(:path)
|
26
|
+
[*options.delete(:path)]
|
27
|
+
else
|
28
|
+
self.path
|
29
|
+
end
|
30
|
+
custom_path += [*options.delete(:path_extension)] if options.include?(:path_extension)
|
31
|
+
respondables = [object]
|
32
|
+
respondables += [*options.delete(:respondable)] if options.include?(:respondable)
|
33
|
+
respondables << self # add self at last
|
34
|
+
custom_path.each do |path_name|
|
35
|
+
if path_name.is_a?(Symbol)
|
36
|
+
# find a respondable which responds_to path_name
|
37
|
+
respondable = respondables.find{ |respondable| respondable.respond_to?(path_name) }
|
38
|
+
if respondable
|
39
|
+
# call the path_name method on the respondable
|
40
|
+
result = value_from_method_call(respondable, respondables, path_name, parameter_matchings)
|
41
|
+
if result.is_a?(Array)
|
42
|
+
# add all entries of an array
|
43
|
+
scope += result
|
44
|
+
else
|
45
|
+
scope << result
|
46
|
+
end
|
47
|
+
else
|
48
|
+
# no object is respondable for this path_name, so just add the symbol to the scope
|
49
|
+
scope << path_name
|
50
|
+
end
|
51
|
+
elsif path_name.is_a?(String)
|
52
|
+
scope << path_name
|
53
|
+
end
|
54
|
+
end
|
55
|
+
return scope
|
56
|
+
end
|
49
57
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
58
|
+
protected
|
59
|
+
# returns the value from method path ond object using parameter_matchings as arguments
|
60
|
+
#
|
61
|
+
# === Params:
|
62
|
+
# * +object+: the object to call the method on
|
63
|
+
# * +respondables+: the objects on which arguments will be searched on
|
64
|
+
# * +method_name+: the method name to call
|
65
|
+
# * +parameter_matchings+: additional parameter_matchings as a Hash
|
66
|
+
def value_from_method_call(object, respondables, method_name, parameter_matchings)
|
67
|
+
method = object.class.instance_method(method_name)
|
68
|
+
if method.arity == 0
|
69
|
+
return object.send(method_name)
|
70
|
+
else
|
71
|
+
return object.send(method_name, *self.compute_arguments_for(respondables, method, parameter_matchings))
|
72
|
+
end
|
73
|
+
end
|
66
74
|
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
75
|
+
# this method will compute all required (and optional) arguments for method on object
|
76
|
+
#
|
77
|
+
# === Params:
|
78
|
+
# * +objects+: the objects on which the arguments should be collected
|
79
|
+
# * +method+: the method on which the arguments should be determined
|
80
|
+
# * +parameter_matchings+: additional paramteters_matchings as a Hash
|
81
|
+
def compute_arguments_for(objects, method, parameter_matchings)
|
82
|
+
args = []
|
83
|
+
parameters = method.parameters
|
84
|
+
parameters.each do |type, name|
|
85
|
+
if parameter_matchings.include?(name)
|
86
|
+
args << parameter_matchings[name]
|
87
|
+
elsif object = objects.find{|o| o.respond_to?(name) }
|
88
|
+
if object.class.instance_method(name).arity == 0
|
89
|
+
args << object.send(name)
|
90
|
+
else
|
91
|
+
method = object.class.instance_method(name)
|
92
|
+
args << object.send(name, *self.compute_arguments_for(objects, method, parameter_matchings))
|
93
|
+
end
|
94
|
+
elsif type == :req
|
95
|
+
raise "Could not find parameter #{name} for method #{method.name}"
|
96
|
+
else
|
97
|
+
break # break if type is :opt and we couldn't find a value
|
98
|
+
end
|
99
|
+
end
|
100
|
+
return args
|
101
|
+
end
|
94
102
|
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
end
|
105
|
-
end
|
103
|
+
# this method will return all modules in a array, each module will be underscored
|
104
|
+
#
|
105
|
+
# === Params:
|
106
|
+
# * +klass+: the klass of which the modules should be used
|
107
|
+
def modules(klass)
|
108
|
+
modules = ActiveSupport::Inflector.deconstantize(klass.name)
|
109
|
+
modules = ActiveSupport::Inflector.underscore(modules)
|
110
|
+
modules.split("::")
|
111
|
+
end
|
106
112
|
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
end
|
126
|
-
end
|
113
|
+
# this method will return a underscored class_name
|
114
|
+
#
|
115
|
+
# Note: plural_class and strip_controller_suffix will be used here
|
116
|
+
#
|
117
|
+
# === Params:
|
118
|
+
# * +klass+: the class on which the name should be get
|
119
|
+
# * +options+: options like plural_class and strip_controller_suffix
|
120
|
+
def class_name(klass, options = {})
|
121
|
+
class_name_options = self.options.merge(options)
|
122
|
+
class_name = ActiveSupport::Inflector.demodulize(klass.name)
|
123
|
+
class_name = ActiveSupport::Inflector.underscore(class_name)
|
124
|
+
class_name = class_name[0, class_name.length - CONTROLLER_SUFFIX.length] if class_name_options[:strip_controller_suffix] && class_name.end_with?(CONTROLLER_SUFFIX)
|
125
|
+
if class_name_options[:plural_class]
|
126
|
+
ActiveSupport::Inflector.pluralize(class_name)
|
127
|
+
else
|
128
|
+
ActiveSupport::Inflector.singularize(class_name)
|
129
|
+
end
|
130
|
+
end
|
127
131
|
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
132
|
+
# returns the method name of the original caller
|
133
|
+
def method_name
|
134
|
+
found_scoped_t_at = nil
|
135
|
+
caller.each_with_index do |call, index|
|
136
|
+
if call.include?("scoped_translation")
|
137
|
+
found_scoped_t_at = index
|
138
|
+
break
|
139
|
+
end
|
140
|
+
end
|
141
|
+
if found_scoped_t_at && call = caller[found_scoped_t_at + 1]
|
142
|
+
if /^(.+?):(\d+)(?::in `(.*)')?/ =~ call
|
143
|
+
return Regexp.last_match[3]
|
144
|
+
end
|
145
|
+
end
|
146
|
+
raise "Failed to get method_name"
|
147
|
+
end
|
144
148
|
|
145
|
-
|
149
|
+
end
|
146
150
|
|
147
151
|
end
|
@@ -1,44 +1,45 @@
|
|
1
1
|
module I18nScopes
|
2
2
|
|
3
|
-
|
4
|
-
|
3
|
+
module TranslationMethods
|
4
|
+
extend ActiveSupport::Concern
|
5
5
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
6
|
+
protected
|
7
|
+
# translates the given key under the configured scope
|
8
|
+
#
|
9
|
+
# === Params:
|
10
|
+
# * +key+: the translation key to lookup
|
11
|
+
# * +options+:
|
12
|
+
# * +path+: +Array+ the path to be overwritten
|
13
|
+
# * +path_extension+: +Array+ an additional path to the one configued using Scope::ClassMethods#i18n_scope (will be attached to the end)
|
14
|
+
# * +respondable+: an array of objects on which the methods should be looked up
|
15
|
+
# * +parameter_matchings+: a hash containing arguments for the dynamic method calls
|
16
|
+
def scoped_translation(scope_helper, *args)
|
17
|
+
options = args.extract_options!
|
18
|
+
|
19
|
+
additional_parameters = if self.respond_to?(:i18n_parameter_matchings)
|
20
|
+
self.i18n_parameter_matchings
|
21
|
+
else
|
22
|
+
{}
|
23
|
+
end
|
24
|
+
additional_parameters.merge!(options.delete(:parameter_matchings)) if options.include?(:parameter_matchings)
|
24
25
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
26
|
+
parameter_matchings = {
|
27
|
+
klass: self.class,
|
28
|
+
object: self,
|
29
|
+
options: options,
|
30
|
+
}.merge(additional_parameters)
|
31
|
+
|
32
|
+
scope = scope_helper.scope_from_path(self, options, parameter_matchings)
|
33
|
+
|
34
|
+
scope += options[:scope] if options.include?(:scope)
|
35
|
+
return I18n.translate *args, options.merge(scope: scope)
|
36
|
+
end
|
30
37
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
end
|
38
|
+
# retusn the i18n_scope_helper instance of TranslationHelper
|
39
|
+
def i18n_scope_helper
|
40
|
+
return self.class.i18n_scope_helper
|
41
|
+
end
|
36
42
|
|
37
|
-
|
38
|
-
def i18n_scope_helper
|
39
|
-
return self.class.i18n_scope_helper
|
40
|
-
end
|
41
|
-
|
42
|
-
end
|
43
|
+
end
|
43
44
|
|
44
45
|
end
|
data/lib/i18n_scopes/version.rb
CHANGED
data/spec/configuration_spec.rb
CHANGED
@@ -2,20 +2,20 @@ require 'spec_helper'
|
|
2
2
|
require 'example_classes/should_have_attached_scoped_t'
|
3
3
|
|
4
4
|
describe I18nScopes::Configuration do
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
5
|
+
I18nScopes.configure do |config|
|
6
|
+
config.plural_classes = true
|
7
|
+
config.strip_controller_suffix = true
|
8
|
+
config.attach_to ShouldHaveAttachedScopedT
|
9
|
+
end
|
10
10
|
|
11
|
-
|
12
|
-
|
11
|
+
let(:configuration) { I18nScopes.configuration }
|
12
|
+
subject { configuration }
|
13
13
|
|
14
|
-
|
15
|
-
|
14
|
+
its(:plural_classes) { should be_true }
|
15
|
+
its(:strip_controller_suffix) { should be_true }
|
16
16
|
|
17
|
-
|
18
|
-
|
19
|
-
|
17
|
+
it 'should attach i18n_scope to ShouldHaveAttachedScopedT' do
|
18
|
+
ShouldHaveAttachedScopedT.should respond_to(:i18n_scope)
|
19
|
+
end
|
20
20
|
|
21
21
|
end
|
@@ -1,27 +1,32 @@
|
|
1
1
|
class ScopeTWithPath
|
2
2
|
|
3
|
-
|
3
|
+
i18n_default_scope "static_prefix", :class_prefix, :with_a_parameter, :class_name
|
4
|
+
i18n_scope :flash, :class_name, :flashes
|
4
5
|
|
5
|
-
|
6
|
-
|
7
|
-
|
6
|
+
def translate
|
7
|
+
t_scoped(:name)
|
8
|
+
end
|
8
9
|
|
9
10
|
def translate_local
|
10
|
-
|
11
|
+
t_scoped(:name, :path => [:overwritten, :locally])
|
11
12
|
end
|
12
13
|
|
13
14
|
def translate_path_extension
|
14
|
-
|
15
|
+
t_scoped(:name, :path_extension => "extension")
|
15
16
|
end
|
16
17
|
|
17
18
|
def translate_with_respondable
|
18
|
-
|
19
|
+
t_scoped(:name, :path_extension => [:type], :respondable => Respondable.new)
|
20
|
+
end
|
21
|
+
|
22
|
+
def translate_flash
|
23
|
+
t_flash(:message)
|
19
24
|
end
|
20
25
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
26
|
+
protected
|
27
|
+
def class_prefix
|
28
|
+
:some_prefix_from_local_class
|
29
|
+
end
|
25
30
|
|
26
31
|
def with_a_parameter(the_parameter)
|
27
32
|
:"with_#{the_parameter}"
|
@@ -1,10 +1,10 @@
|
|
1
1
|
module SomeModule
|
2
|
-
|
2
|
+
class ScopeTWithPathInModule
|
3
3
|
|
4
|
-
|
4
|
+
i18n_default_scope :modules, :local, :class_name
|
5
5
|
|
6
6
|
def translate
|
7
|
-
|
7
|
+
t_scoped(:name)
|
8
8
|
end
|
9
9
|
|
10
10
|
protected
|
@@ -20,5 +20,5 @@ module SomeModule
|
|
20
20
|
"moddd_#{modules}"
|
21
21
|
end
|
22
22
|
|
23
|
-
|
23
|
+
end
|
24
24
|
end
|
data/spec/include_scope_spec.rb
CHANGED
@@ -5,15 +5,15 @@ require 'example_classes/should_have_attached_scoped_t'
|
|
5
5
|
# Testing I18nScopes::Scope
|
6
6
|
describe ShouldHaveAttachedScopedT do
|
7
7
|
|
8
|
-
|
9
|
-
|
8
|
+
I18nScopes.configuration.attach_to(ShouldHaveAttachedScopedT)
|
9
|
+
subject { ShouldHaveAttachedScopedT }
|
10
10
|
|
11
|
-
|
12
|
-
|
13
|
-
|
11
|
+
it 'should respond to i18n_scope_helper' do
|
12
|
+
subject.should respond_to(:i18n_scope_helper)
|
13
|
+
end
|
14
14
|
|
15
|
-
|
16
|
-
|
17
|
-
|
15
|
+
it 'should respond to i18n_scope' do
|
16
|
+
subject.should respond_to(:i18n_scope)
|
17
|
+
end
|
18
18
|
|
19
19
|
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'example_classes/scope_t_with_path'
|
3
|
+
require 'example_classes/inherited'
|
4
|
+
|
5
|
+
describe Inherited do
|
6
|
+
|
7
|
+
its(:translate) { should == "InheritedScope" }
|
8
|
+
|
9
|
+
its(:translate_flash) { should == "InheritedScopeOverwritten" }
|
10
|
+
|
11
|
+
end
|
data/spec/locales/en.yml
CHANGED
@@ -8,6 +8,8 @@ en:
|
|
8
8
|
name: ScopeTWithPathPathExtension
|
9
9
|
normal:
|
10
10
|
name: ScopeTWithPathAndRespondable
|
11
|
+
inherited:
|
12
|
+
name: InheritedScope
|
11
13
|
|
12
14
|
some_module:
|
13
15
|
prefix_suffix:
|
@@ -15,4 +17,10 @@ en:
|
|
15
17
|
name: ScopeTWithPathTranslationAndModule
|
16
18
|
overwritten:
|
17
19
|
locally:
|
18
|
-
name: ScopeTWithPathLocallyOverwritten
|
20
|
+
name: ScopeTWithPathLocallyOverwritten
|
21
|
+
scope_t_with_path:
|
22
|
+
flashes:
|
23
|
+
message: ScopeTWithPathFromScope
|
24
|
+
inheritance_overwritten:
|
25
|
+
flashes:
|
26
|
+
message: InheritedScopeOverwritten
|
data/spec/scope_spec.rb
CHANGED
@@ -3,18 +3,19 @@ require 'example_classes/should_define_scope'
|
|
3
3
|
|
4
4
|
# Testing I18nScopes::Scope
|
5
5
|
describe ShouldDefineScope do
|
6
|
-
I18nScopes.configuration.attach_to(ShouldDefineScope)
|
7
|
-
let(:should_define_scope) { ShouldDefineScope.new }
|
8
|
-
subject { should_define_scope }
|
9
6
|
|
10
|
-
|
11
|
-
|
12
|
-
|
7
|
+
I18nScopes.configuration.attach_to(ShouldDefineScope)
|
8
|
+
let(:should_define_scope) { ShouldDefineScope.new }
|
9
|
+
subject { should_define_scope }
|
13
10
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
11
|
+
it 'should return I18nScopes::TranslationHelper for i18n_scope_helper' do
|
12
|
+
ShouldDefineScope.i18n_scope_helper[:default].should be_instance_of(I18nScopes::TranslationHelper)
|
13
|
+
end
|
14
|
+
|
15
|
+
[:scoped_translation, :i18n_scope_helper,].each do |method|
|
16
|
+
it "should respond to #{method}" do
|
17
|
+
should_define_scope.should respond_to(method)
|
18
|
+
end
|
19
|
+
end
|
19
20
|
|
20
21
|
end
|
@@ -4,13 +4,15 @@ require 'example_classes/respondable'
|
|
4
4
|
|
5
5
|
describe ScopeTWithPath do
|
6
6
|
|
7
|
-
|
7
|
+
|
8
8
|
its(:translate) { should == "ScopeTWithPathTranslationFromFile"}
|
9
9
|
|
10
10
|
its(:translate_local) { should == "ScopeTWithPathLocallyOverwritten"}
|
11
11
|
|
12
|
-
its(:translate_path_extension)
|
12
|
+
its(:translate_path_extension) { should == "ScopeTWithPathPathExtension" }
|
13
13
|
|
14
|
-
its(:translate_with_respondable)
|
14
|
+
its(:translate_with_respondable) { should == "ScopeTWithPathAndRespondable" }
|
15
|
+
|
16
|
+
its(:translate_flash) { should == "ScopeTWithPathFromScope" }
|
15
17
|
|
16
18
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: i18n_scopes
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.2.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-07-
|
12
|
+
date: 2012-07-15 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rspec
|
@@ -43,17 +43,20 @@ files:
|
|
43
43
|
- i18n_scopes.gemspec
|
44
44
|
- lib/i18n_scopes.rb
|
45
45
|
- lib/i18n_scopes/configuration.rb
|
46
|
+
- lib/i18n_scopes/option_accessor.rb
|
46
47
|
- lib/i18n_scopes/scope.rb
|
47
48
|
- lib/i18n_scopes/translation_helper.rb
|
48
49
|
- lib/i18n_scopes/translation_methods.rb
|
49
50
|
- lib/i18n_scopes/version.rb
|
50
51
|
- spec/configuration_spec.rb
|
52
|
+
- spec/example_classes/inherited.rb
|
51
53
|
- spec/example_classes/respondable.rb
|
52
54
|
- spec/example_classes/scope_t_with_path.rb
|
53
55
|
- spec/example_classes/scope_t_with_path_in_module.rb
|
54
56
|
- spec/example_classes/should_define_scope.rb
|
55
57
|
- spec/example_classes/should_have_attached_scoped_t.rb
|
56
58
|
- spec/include_scope_spec.rb
|
59
|
+
- spec/inherited_spec.rb
|
57
60
|
- spec/locales/en.yml
|
58
61
|
- spec/scope_spec.rb
|
59
62
|
- spec/should_define_scope_in_module_spec.rb
|
@@ -82,16 +85,18 @@ rubyforge_project:
|
|
82
85
|
rubygems_version: 1.8.24
|
83
86
|
signing_key:
|
84
87
|
specification_version: 3
|
85
|
-
summary: This gem will attach a
|
88
|
+
summary: This gem will attach a t_scoped method to your class. The scope will be configureable
|
86
89
|
in your class or globally.
|
87
90
|
test_files:
|
88
91
|
- spec/configuration_spec.rb
|
92
|
+
- spec/example_classes/inherited.rb
|
89
93
|
- spec/example_classes/respondable.rb
|
90
94
|
- spec/example_classes/scope_t_with_path.rb
|
91
95
|
- spec/example_classes/scope_t_with_path_in_module.rb
|
92
96
|
- spec/example_classes/should_define_scope.rb
|
93
97
|
- spec/example_classes/should_have_attached_scoped_t.rb
|
94
98
|
- spec/include_scope_spec.rb
|
99
|
+
- spec/inherited_spec.rb
|
95
100
|
- spec/locales/en.yml
|
96
101
|
- spec/scope_spec.rb
|
97
102
|
- spec/should_define_scope_in_module_spec.rb
|