fishman-i18n_routing 0.4.9

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,99 @@
1
+ 0.4.7 (February 14, 2011)
2
+
3
+ * Fix bug in empty translation handling
4
+ * Hack Rack::Mount to handle :locale constraints in top of i18n_locale
5
+ * Fix requirements bug introduced by Rails 3.0.4
6
+ * Add Gemfile with bundler for easy spec on different rails versions
7
+
8
+ 0.4.6 (February 14, 2011)
9
+
10
+ * Handle empty translation
11
+
12
+ 0.4.5 (November 04, 2010)
13
+
14
+ * Fixing Rails 3 scope bug with missing / and no translations
15
+
16
+ 0.4.4 (November 03, 2010)
17
+
18
+ * Fix bug with locale with a dash like pt-br
19
+
20
+ 0.4.3 (October 10, 2010)
21
+
22
+ * Named route can be translated by name or by path
23
+
24
+ 0.4.2 (September 20, 2010)
25
+
26
+ * Fix a Rails3 bug, enabling again to do things like that: get :one, :two, :three
27
+
28
+ 0.4.1 (September 11, 2010)
29
+
30
+ * Fix a Rails3 bug for named routes and prefixed path
31
+
32
+ 0.4.0 (September 08, 2010)
33
+
34
+ * Full support for Rails 3.0.0
35
+
36
+ 0.3.8 (August 30, 2010)
37
+
38
+ * Support the first Rails3 official release (but nested resources is still broken)
39
+
40
+ 0.3.7 (August 26, 2010)
41
+
42
+ * Support Rails3 RC2 thanks to fwalch / Rails3 final will probably require a new version of i18n_routing
43
+ * Not everything works on RC2 (nested resources), will be fixed when Rails3 will be officially released.
44
+
45
+ 0.3.6 (June 13, 2010)
46
+
47
+ * Works even if translations are the same as the translated name
48
+
49
+ 0.3.5 (June 9, 2010)
50
+
51
+ * Clean up some .to_sym in order to avoid unnecessary symbols during runtime
52
+ * Works with both I18n.locale as string or as symbol
53
+ * Try to fix a Pathname instead of string issue
54
+
55
+ 0.3.4 (June 3, 2010)
56
+
57
+ * Fix Rails3 issue with nested single resource again and pluralize controller name as it should be
58
+
59
+ 0.3.3 (June 2, 2010)
60
+
61
+ * Fix Rails3 issue with nested single resource
62
+
63
+ 0.3.2 (June 2, 2010)
64
+
65
+ * Add automatically config/locales/*.yml in the i18n load path in order to fix Rails3 issue
66
+
67
+ 0.3.1 (May 27, 2010)
68
+
69
+ * Add a small Rails3 verification
70
+
71
+ 0.3.0 (May 27, 2010)
72
+
73
+ * Add support for translating path_names, member and collection
74
+ * Fix Rails3 nested resources
75
+ * All specs are now passing under both Rails 2.3.5 and Rails 3
76
+
77
+ 0.2.4 (Apr 21, 2010)
78
+
79
+ * Fix latest Rails3 edge compatibility (previous rails3 beta version not supported any more)
80
+
81
+ 0.2.3 (Apr 21, 2010)
82
+
83
+ * Works on ruby 1.9.2-head
84
+
85
+ 0.2.2 (Apr 21, 2010)
86
+
87
+ * Add I18n gem dependency
88
+
89
+ 0.2.1 (Apr 09, 2010)
90
+
91
+ * Minor Rails3 modification, added gemspec and pushed gem on gemcutter
92
+
93
+ 0.2.0 (Apr 07, 2010)
94
+
95
+ * All specs pass for Rails2, including nested deep resources
96
+
97
+ 0.1.0 (Mar 22, 2010)
98
+
99
+ * Initial release
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source "http://rubygems.org"
2
+ gem "rails", '3.0.6'
3
+ gem 'rspec', '>=2.5.0'
@@ -0,0 +1,81 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ abstract (1.0.0)
5
+ actionmailer (3.0.6)
6
+ actionpack (= 3.0.6)
7
+ mail (~> 2.2.15)
8
+ actionpack (3.0.6)
9
+ activemodel (= 3.0.6)
10
+ activesupport (= 3.0.6)
11
+ builder (~> 2.1.2)
12
+ erubis (~> 2.6.6)
13
+ i18n (~> 0.5.0)
14
+ rack (~> 1.2.1)
15
+ rack-mount (~> 0.6.14)
16
+ rack-test (~> 0.5.7)
17
+ tzinfo (~> 0.3.23)
18
+ activemodel (3.0.6)
19
+ activesupport (= 3.0.6)
20
+ builder (~> 2.1.2)
21
+ i18n (~> 0.5.0)
22
+ activerecord (3.0.6)
23
+ activemodel (= 3.0.6)
24
+ activesupport (= 3.0.6)
25
+ arel (~> 2.0.2)
26
+ tzinfo (~> 0.3.23)
27
+ activeresource (3.0.6)
28
+ activemodel (= 3.0.6)
29
+ activesupport (= 3.0.6)
30
+ activesupport (3.0.6)
31
+ arel (2.0.9)
32
+ builder (2.1.2)
33
+ diff-lcs (1.1.2)
34
+ erubis (2.6.6)
35
+ abstract (>= 1.0.0)
36
+ i18n (0.5.0)
37
+ mail (2.2.16)
38
+ activesupport (>= 2.3.6)
39
+ i18n (>= 0.4.0)
40
+ mime-types (~> 1.16)
41
+ treetop (~> 1.4.8)
42
+ mime-types (1.16)
43
+ polyglot (0.3.1)
44
+ rack (1.2.2)
45
+ rack-mount (0.6.14)
46
+ rack (>= 1.0.0)
47
+ rack-test (0.5.7)
48
+ rack (>= 1.0)
49
+ rails (3.0.6)
50
+ actionmailer (= 3.0.6)
51
+ actionpack (= 3.0.6)
52
+ activerecord (= 3.0.6)
53
+ activeresource (= 3.0.6)
54
+ activesupport (= 3.0.6)
55
+ bundler (~> 1.0)
56
+ railties (= 3.0.6)
57
+ railties (3.0.6)
58
+ actionpack (= 3.0.6)
59
+ activesupport (= 3.0.6)
60
+ rake (>= 0.8.7)
61
+ thor (~> 0.14.4)
62
+ rake (0.8.7)
63
+ rspec (2.5.0)
64
+ rspec-core (~> 2.5.0)
65
+ rspec-expectations (~> 2.5.0)
66
+ rspec-mocks (~> 2.5.0)
67
+ rspec-core (2.5.1)
68
+ rspec-expectations (2.5.0)
69
+ diff-lcs (~> 1.1.2)
70
+ rspec-mocks (2.5.0)
71
+ thor (0.14.6)
72
+ treetop (1.4.9)
73
+ polyglot (>= 0.3.1)
74
+ tzinfo (0.3.26)
75
+
76
+ PLATFORMS
77
+ ruby
78
+
79
+ DEPENDENCIES
80
+ rails (= 3.0.6)
81
+ rspec (>= 2.5.0)
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2010 Guillaume Luccisano - g-mai|: guillaume.luccisano
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,32 @@
1
+ = I18nRouting
2
+
3
+ I18n_routing is a plugin for Ruby on Rails that lets you easily translate your routes trough the I18n api included in Rails since version 2.2
4
+
5
+ All necessary informations are available on the wiki: http://wiki.github.com/kwi/i18n_routing
6
+
7
+ For any question, use the i18_routing google group: http://groups.google.com/group/i18n-routing
8
+
9
+ Works with Rails 2.3 and Rails 3.0
10
+ => Rails3 beta and RC versions are no longer supported !
11
+
12
+ == TODO for next releases (written the 9th of June)
13
+
14
+ * Handle multiple translations for same resources name (Example: nested and not nested resources)
15
+ * Handle namespace translation (and path_prefix on Rails3)
16
+
17
+ == I18n gem version warning
18
+
19
+ Be careful when running Rails 2.3 with the shipped i18n gem: this is an old i18n version and i18_routing will install the latest i18n version as a gem.
20
+ This latest version may be incompatible with some old usages.
21
+ Furthermore, if the i18n gem is present on your system, Rails will load it and skip the shipped version; Keep that in mind.
22
+
23
+ == Contributors
24
+
25
+ * kwi (Guillaume Luccisano)
26
+ * bigtiger (Jim Remsik)
27
+ * mixr (Reiner Dieterich)
28
+ * fwalch
29
+ * doubledrones: h13ronim (Marcin Michałowski)
30
+ * rudionrails (Rudolf Schmidt)
31
+
32
+ Copyright (c) 2010 Guillaume Luccisano - g-mai|: guillaume.luccisano, released under the MIT license
@@ -0,0 +1,28 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require 'rspec/core/rake_task'
4
+
5
+ # Now using RSpec 2
6
+
7
+ desc "Run specs for current Rails version"
8
+ RSpec::Core::RakeTask.new do |t|
9
+ t.pattern = "spec/**/*_spec.rb"
10
+ t.verbose = true
11
+ # t.ruby_opts = lambda {
12
+ # @rails_spec_version ? ["-c --format specdoc -- rails_spec_version=#{@rails_spec_version}"] : ["-c --format specdoc"]
13
+ # }
14
+ end
15
+
16
+ task :default => :spec
17
+
18
+ desc "Run Rails 2.x specs"
19
+ task :rails2_spec do
20
+ @rails_spec_version = 2
21
+ Rake::Task['spec'].invoke
22
+ end
23
+
24
+ desc "Run Rails 3.x specs"
25
+ task :rails3_spec do
26
+ @rails_spec_version = 3
27
+ Rake::Task['spec'].invoke
28
+ end
data/init.rb ADDED
@@ -0,0 +1,2 @@
1
+ # encoding: utf-8
2
+ require 'i18n_routing'
@@ -0,0 +1,8 @@
1
+ # encoding: utf-8
2
+ require 'i18n_routing_common'
3
+
4
+ if Rails.version < '3'
5
+ require 'i18n_routing_rails2'
6
+ else
7
+ require 'i18n_routing_rails3'
8
+ end
@@ -0,0 +1,52 @@
1
+ # encoding: utf-8
2
+
3
+ # I18nRouting module for common usage methods
4
+ module I18nRouting
5
+ def self.locale_escaped(locale)
6
+ locale.to_s.downcase.gsub('-', '_')
7
+ end
8
+
9
+ # Return the correct translation for given values
10
+ def self.translation_for(name, type = :resources, option = nil)
11
+ # First, if an option is given, try to get the translation in the routes scope
12
+ if option
13
+ default = "{option}Noi18nRoutingTranslation"
14
+ t = I18n.t(option, :scope => "routes.#{name}.#{type}", :default => default)
15
+ return (t == default ? nil : t)
16
+ else
17
+ default = "{name}Noi18nRoutingTranslation"
18
+
19
+ # Try to get the translation in routes namescope first
20
+ t = I18n.t(:as, :scope => "routes.#{name}", :default => default)
21
+
22
+ return t if t and t != default
23
+
24
+ t = I18n.t(name.to_s, :scope => type, :default => default)
25
+ return (t == default ? nil : t)
26
+ end
27
+ end
28
+
29
+ DefaultPathNames = [:new, :edit]
30
+ PathNamesKeys = [:path_names, :member, :collection]
31
+
32
+ # Return path names hash for given resource
33
+ def self.path_names(name, options)
34
+ h = (options[:path_names] || {}).dup
35
+
36
+ path_names = DefaultPathNames
37
+ PathNamesKeys.each do |v|
38
+ path_names += options[v].keys if options[v] and Hash === options[v]
39
+ end
40
+
41
+ path_names.each do |pn|
42
+ n = translation_for(name, :path_names, pn)
43
+ n = nil if n == pn.to_s
44
+ # Get default path_names in path_names scope if no path_names found
45
+ n ||= I18n.t(pn, :scope => :path_names, :default => name.to_s)
46
+
47
+ h[pn] = n if n and n != name.to_s
48
+ end
49
+
50
+ return h
51
+ end
52
+ end
@@ -0,0 +1,237 @@
1
+ # encoding: utf-8
2
+
3
+ #
4
+ # WARNING : Old and dirty Rails 2.x code
5
+ # Need clean up and intensive refactoring
6
+ #
7
+
8
+ module ActionController
9
+ module Routing
10
+ class Route #:nodoc:
11
+ alias_method :mkd_initialize, :initialize
12
+ def initialize(segments = [], requirements = {}, conditions = {})
13
+ @glang = requirements.delete(:glang)
14
+ mkd_initialize(segments, requirements, conditions)
15
+ end
16
+
17
+ private
18
+ alias_method :mkd_generation_requirements, :generation_requirements
19
+ # Add locale requirements to ensure good route is used when using url_for
20
+ def generation_requirements
21
+ r = mkd_generation_requirements
22
+ if @glang and !r.blank?
23
+ r << " and I18n.locale.to_sym == :'#{@glang}'"
24
+ end
25
+
26
+ return r
27
+ end
28
+ end
29
+ end
30
+ end
31
+
32
+ module ActionController
33
+ module Routing
34
+ class RouteSet #:nodoc:
35
+ attr :locales, true
36
+ attr :i18n_verbose, true
37
+
38
+ class Mapper
39
+ def localized(locales = I18n.available_locales, opts = {})
40
+ old_value = @set.locales
41
+ @set.locales = locales
42
+ @set.i18n_verbose ||= opts.delete(:verbose)
43
+ yield
44
+ ensure
45
+ @set.locales = old_value
46
+ end
47
+ end
48
+
49
+ class NamedRouteCollection #:nodoc:
50
+ alias_method :mkd_define_url_helper, :define_url_helper
51
+ def define_url_helper(route, name, kind, options)
52
+ gl = Thread.current[:globalized]
53
+
54
+ mkd_define_url_helper(route, name, kind, options)
55
+
56
+ if gl
57
+ selector = url_helper_name(name, kind)
58
+
59
+ rlang = if i = name.to_s.rindex("_#{gl}")
60
+ "#{selector.to_s[0, i]}_glang_#{gl}#{selector.to_s[i + "_#{gl}".size, selector.to_s.size]}"
61
+ elsif (gls = Thread.current[:globalized_s]) and i = name.to_s.rindex("_#{gls}")
62
+ "#{selector.to_s[0, i]}_glang_#{gls}#{selector.to_s[i + "_#{gls}".size, selector.to_s.size]}"
63
+ else
64
+ "glang_#{selector}"
65
+ end
66
+
67
+ # surcharge de l'helper
68
+ @module.module_eval <<-end_eval # We use module_eval to avoid leaks
69
+ alias_method :gl#{selector}, :#{selector}
70
+
71
+ def #{selector}(*args)
72
+ selector_g = '#{rlang}'.gsub('glang', I18nRouting.locale_escaped(I18n.locale)).to_sym
73
+
74
+ #logger.debug "Call routes : #{selector} => \#{selector_g} (#{rlang}) "
75
+ #puts "Call routes : #{selector} => \#{selector_g} (#{rlang}) Found:\#{respond_to? selector_g and selector_g != :#{selector}}"
76
+ if respond_to? selector_g and selector_g != :#{selector}
77
+ send(selector_g, *args)
78
+ else
79
+ gl#{selector}(*args)
80
+ end
81
+ end
82
+ protected :gl#{selector}
83
+ end_eval
84
+ end
85
+ end
86
+ end
87
+
88
+ alias_method :gl_add_named_route, :add_named_route
89
+ def add_named_route(name, path, options = {}) #:nodoc:
90
+ if @locales and !path.blank? and !Thread.current[:i18n_no_named_localization]
91
+ # Here, try to translate standard named routes
92
+ name = name.to_s
93
+
94
+ stored_locale = I18n.locale
95
+ @locales.each do |l|
96
+ I18n.locale = l
97
+ nt = "#{I18nRouting.locale_escaped(l)}_#{name}"
98
+ t = I18nRouting.translation_for(name, :named_routes) || I18nRouting.translation_for(path, :named_routes_path)
99
+ if nt != name and !t.blank?
100
+ gl_add_named_route(nt, t, options.merge(:glang => l))
101
+ puts("[I18n] > localize %-10s: %40s (%s) => %s" % ['route', name, l, t]) if @i18n_verbose
102
+ end
103
+ end
104
+ I18n.locale = stored_locale
105
+
106
+ old_v = Thread.current[:globalized]
107
+ Thread.current[:globalized] = true
108
+ gl_add_named_route(name, path, options)
109
+ Thread.current[:globalized] = old_v
110
+ return
111
+ end
112
+
113
+ gl_add_named_route(name, path, options)
114
+ end
115
+ end
116
+ end
117
+ end
118
+
119
+ module ActionController
120
+ module Resources
121
+ class Resource
122
+ alias_method :mkd_initialize, :initialize
123
+ def initialize(entities, options)
124
+ @real_path = options.delete(:real_path)
125
+ @real_path = @real_path.to_s.singularize if @real_path
126
+
127
+ mkd_initialize(entities, options)
128
+ end
129
+
130
+ def nesting_name_prefix
131
+ @real_path ? "#{shallow_name_prefix}#{@real_path}_" : "#{shallow_name_prefix}#{singular}_"
132
+ end
133
+
134
+ def nesting_path_prefix
135
+ @nesting_path_prefix ||= (@real_path ? "#{shallow_path_prefix}/#{path_segment}/:#{@real_path}_id" : "#{shallow_path_prefix}/#{path_segment}/:#{singular}_id")
136
+ end
137
+ end
138
+
139
+ def switch_globalized_state(state)
140
+ old_g = Thread.current[:globalized]
141
+ Thread.current[:globalized] = state
142
+ yield
143
+ Thread.current[:globalized] = old_g
144
+ end
145
+
146
+ def switch_no_named_localization(state)
147
+ old_g = Thread.current[:i18n_no_named_localization]
148
+ Thread.current[:i18n_no_named_localization] = state
149
+ yield
150
+ Thread.current[:i18n_no_named_localization] = old_g
151
+ end
152
+
153
+ def create_globalized_resources(type, namespace, *entities, &block)
154
+ Thread.current[:i18n_nested_deep] ||= 0
155
+ Thread.current[:i18n_nested_deep] += 1
156
+
157
+ if @set.locales
158
+ name = entities.dup.shift.to_s
159
+
160
+ options = entities.extract_options!
161
+ opts = options.dup
162
+
163
+ locales = @set.locales
164
+ localized(nil) do
165
+ stored_locale = I18n.locale
166
+ locales.each do |l|
167
+ I18n.locale = l
168
+ nt = "#{I18nRouting.locale_escaped(l)}_#{name}"
169
+ if nt != name and !(t = I18nRouting.translation_for(name, namespace)).blank?
170
+ opts[:as] = t
171
+ opts[:glang] = l
172
+ opts[:controller] ||= name.to_s.pluralize
173
+ opts[:real_path] = opts[:singular] || name
174
+ opts[:path_names] = I18nRouting.path_names(name, options)
175
+ path_prefix_t = I18n.t(:path_prefix, :scope => :"routes.#{name}", :default => "NoPathPrefixTranslation")
176
+ opts[:path_prefix] = path_prefix_t unless path_prefix_t == "NoPathPrefixTranslation"
177
+
178
+ localized([l]) do
179
+ switch_no_named_localization(true) do
180
+ send(type, nt.to_sym, opts, &block)
181
+ end
182
+ end
183
+ puts("[I18n] > localize %-10s: %40s (%s) => %s" % [namespace, nt, l, t]) if @set.i18n_verbose
184
+ end
185
+ end
186
+ I18n.locale = stored_locale
187
+
188
+
189
+ if Thread.current[:i18n_nested_deep] < 2
190
+ switch_no_named_localization(nil) do
191
+ switch_globalized_state(true) do
192
+ send(type, *(entities << options), &block)
193
+ end
194
+ end
195
+ end
196
+ end
197
+
198
+ else
199
+ send(type, *entities, &block)
200
+ end
201
+
202
+ Thread.current[:i18n_nested_deep] -= 1
203
+ end
204
+
205
+ alias_method :gl_resources, :resources
206
+ def resources(*entities, &block)
207
+ create_globalized_resources(:gl_resources, :resources, *entities, &block)
208
+ end
209
+
210
+ alias_method :gl_resource, :resource
211
+ def resource(*entities, &block)
212
+ create_globalized_resources(:gl_resource, :resource, *entities, &block)
213
+ end
214
+
215
+ private
216
+ alias_method :gl_action_options_for, :action_options_for
217
+ def action_options_for(action, resource, method = nil, resource_options = {})
218
+ opts = gl_action_options_for(action, resource, method, resource_options)
219
+
220
+ if Thread.current[:globalized]
221
+ Thread.current[:globalized] = resource.plural
222
+ if resource.uncountable?
223
+ Thread.current[:globalized] = resource.plural.to_s + '_index'
224
+ end
225
+ Thread.current[:globalized_s] = resource.singular
226
+ else
227
+ Thread.current[:globalized] = nil
228
+ Thread.current[:globalized_s] = nil
229
+ end
230
+ if resource.options[:glang]
231
+ opts[:glang] = resource.options[:glang]
232
+ end
233
+
234
+ opts
235
+ end
236
+ end
237
+ end