translate_routes_rails_2_3 0.0.2 → 3.0.3
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.markdown +47 -43
- data/lib/route_translator.rb +306 -0
- data/lib/translate_routes.rb +1 -219
- data/lib/translate_routes_test_helper.rb +4 -4
- data/test/translate_routes_test.rb +141 -180
- metadata +6 -8
- data/ChangeLog +0 -22
- data/lib/translate_routes_i18n_available_locales.rb +0 -23
data/README.markdown
CHANGED
@@ -1,71 +1,69 @@
|
|
1
|
-
TranslateRoutes
|
1
|
+
TranslateRoutes
|
2
2
|
===============
|
3
3
|
|
4
|
-
This branch works with Rails
|
4
|
+
This branch works with Rails 3.x, you can find branches for Rails [2.1.x](http://github.com/raul/translate_routes/tree/rails2.1), [2.2.x](http://github.com/raul/translate_routes/tree/rails2.2) and [2.3.x](http://github.com/raul/translate_routes/tree/rails2.3)
|
5
5
|
|
6
|
-
This Rails plugin provides a simple way to translate your URLs to any number of languages, even on a fully working application.
|
6
|
+
This Rails plugin provides a simple way to translate your URLs to any number of languages, even on a fully working application.
|
7
7
|
|
8
|
-
It works fine with all kind of routing definitions, including RESTful and named routes.
|
8
|
+
It works fine with all kind of routing definitions, including RESTful and named routes.
|
9
9
|
**Your current code will remain untouched**: your current routing code, helpers and links will be translated transparently - even in your tests.
|
10
10
|
(Un)installing it is a very clean and simple process, so why don't you give it a chance? ;)
|
11
11
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
12
|
+
Installation
|
13
|
+
------------
|
14
|
+
Add translate_routes to your `Gemfile`:
|
15
|
+
|
16
|
+
gem 'translate_routes'
|
17
|
+
|
18
|
+
And let bundle do the rest:
|
17
19
|
|
20
|
+
bundle install
|
18
21
|
|
19
|
-
Quick
|
22
|
+
Quick Start
|
20
23
|
-----------
|
21
24
|
|
22
|
-
Let's
|
25
|
+
1) Let's imagine you have this `routes.rb` file:
|
23
26
|
|
24
|
-
|
25
|
-
|
27
|
+
TranslateRoutesApp::Application.routes.draw do
|
28
|
+
match 'contact' => 'contact#index'
|
26
29
|
end
|
27
30
|
|
28
|
-
|
29
|
-
|
30
|
-
2) Write your translations on a standard YAML file (e.g: i18n-routes.yml), including the locales and it translations pairs:
|
31
|
-
|
32
|
-
es:
|
33
|
-
contact: contacto
|
34
|
-
|
31
|
+
You can see the available routes with the `rake routes` task:
|
35
32
|
|
36
|
-
3) Append a line to your routes.rb file to activate the translations. If you loaded the translations file with
|
37
|
-
your other I18n translations files, the line will be:
|
38
33
|
|
39
|
-
|
40
|
-
|
41
|
-
and if you want to keep the file separated (e.g: config/i18n-routes.yml), the line to append is:
|
34
|
+
contact /contact(.:format) {:controller=>"contact", :action=>"index"}
|
42
35
|
|
43
|
-
|
36
|
+
2) Now write your translations on a standard YAML file (e.g: in `/config/i18n-routes.yml`), including all the locales and their translations pairs:
|
44
37
|
|
45
|
-
|
38
|
+
en:
|
39
|
+
# you can leave empty locales, for example the default one
|
40
|
+
es:
|
41
|
+
contact: contacto
|
46
42
|
|
43
|
+
3) Append this line in your `routes.rb` file to activate the translations specifying the path of the translations file:
|
47
44
|
|
48
|
-
|
49
|
-
contact_en_us_path /contact {:locale=>"'en'", :controller=>"contact", :action=>"index"}
|
45
|
+
ActionDispatch::Routing::Translator.translate_from_file('config','i18n-routes.yml')
|
50
46
|
|
47
|
+
4) Execute `rake routes` to see the new routes:
|
51
48
|
|
52
|
-
|
49
|
+
contact_es /es/contacto(.:format) {:controller=>"contact", :action=>"index"}
|
50
|
+
contact_en /contact(.:format) {:controller=>"contact", :action=>"index"}
|
53
51
|
|
54
|
-
|
52
|
+
5) Include this filter in your ApplicationController:
|
55
53
|
|
56
54
|
before_filter :set_locale_from_url
|
57
55
|
|
58
|
-
Now your application recognizes the different routes and sets the `I18n.locale` value
|
59
|
-
but what about the routes generation? As you can see on the previous `rake routes` execution, the
|
60
|
-
`contact_es_es_path` and `contact_en_us_path` routing helpers have been generated and are
|
61
|
-
available in your controllers and views. Additionally, a `contact_path` helper has been generated, which
|
62
|
-
generates the routes according to the current request's locale. This way your link
|
56
|
+
Now your application recognizes the different routes and sets the `I18n.locale` value in your controllers,
|
57
|
+
but what about the routes generation? As you can see on the previous `rake routes` execution, the
|
58
|
+
`contact_es_es_path` and `contact_en_us_path` routing helpers have been generated and are
|
59
|
+
available in your controllers and views. Additionally, a `contact_path` helper has been generated, which
|
60
|
+
generates the routes according to the current request's locale. This way your link
|
63
61
|
|
64
62
|
This means that if you use named routes **you don't need to modify your application links** because the routing helpers are automatically adapted to the current locale.
|
65
63
|
|
66
|
-
|
64
|
+
6) Hey, but what about my tests?
|
67
65
|
|
68
|
-
Of course, your functional and integration testing involves some requests.
|
66
|
+
Of course, your functional and integration testing involves some requests.
|
69
67
|
The plugin includes some code to add a default locale parameter so they can remain untouched.
|
70
68
|
Append it to your `test_helper` and it will be applied.
|
71
69
|
|
@@ -80,24 +78,30 @@ Feedback, questions and comments will be always welcome at raul@murciano.net
|
|
80
78
|
Credits
|
81
79
|
-------
|
82
80
|
* Main development:
|
83
|
-
* Raul Murciano <http://raul.murciano.net> - code
|
84
|
-
* Domestika INTERNET S.L <http://domestika.org> - incredible support, really nice people to work with!
|
81
|
+
* Raul Murciano <http://raul.murciano.net> - code
|
82
|
+
* Domestika INTERNET S.L <http://domestika.org> - incredible support, really nice people to work with!
|
85
83
|
|
86
84
|
* Contributors:
|
87
85
|
* [Aitor Garay-Romero](http://github.com/aitorgr)
|
88
86
|
* [Christian Hølmer](http://github.com/hoelmer)
|
89
87
|
* Nico Ritsche
|
90
88
|
* [Cedric Darricau](http://github.com/devsigner)
|
89
|
+
* [Olivier Gonzalez](http://github.com/gonzoyumo)
|
90
|
+
* [Kristian Mandrup](http://github.com/kristianmandrup)
|
91
|
+
* [Pieter Visser](http://github.com/pietervisser)
|
92
|
+
* [Marian Theisen](http://github.com/cice)
|
93
|
+
* [Enric Lluelles](http://github.com/enriclluelles)
|
94
|
+
* [Jaime Iniesta](http://github.com/jaimeiniesta)
|
91
95
|
|
92
96
|
Rails routing resources
|
93
97
|
-----------------------
|
94
|
-
* David Black's 'Rails Routing' ebook rocks! - 'Ruby for Rails' too, BTW.
|
98
|
+
* David Black's 'Rails Routing' ebook rocks! - 'Ruby for Rails' too, BTW.
|
95
99
|
* Obie Fernandez's 'The Rails Way' - the definitive RoR reference, great work Obie!
|
96
100
|
* As a part of the impressive Rails Guides set there is an [awesome document about rails routing](http://guides.rails.info/routing_outside_in.html) by Mike Gunderloy:
|
97
101
|
|
98
102
|
|
99
103
|
License
|
100
104
|
-------
|
101
|
-
Copyright (c) 2007 Released under the MIT license (see MIT-LICENSE)
|
102
|
-
Raul Murciano <http://raul.murciano.net>
|
105
|
+
Copyright (c) 2007 Released under the MIT license (see MIT-LICENSE)
|
106
|
+
Raul Murciano <http://raul.murciano.net>
|
103
107
|
Domestika INTERNET S.L. <http://domestika.org>
|
@@ -0,0 +1,306 @@
|
|
1
|
+
|
2
|
+
# This class knows nothing
|
3
|
+
# about Rails.root or Rails.application.routes, and therefor is easier to
|
4
|
+
# test without an Rails App.
|
5
|
+
class RouteTranslator
|
6
|
+
TRANSLATABLE_SEGMENT = /^(\w+)(\()?/.freeze
|
7
|
+
LOCALE_PARAM_KEY = :locale.freeze
|
8
|
+
ROUTE_HELPER_CONTAINER = [
|
9
|
+
ActionController::Base,
|
10
|
+
ActionView::Base,
|
11
|
+
ActionMailer::Base,
|
12
|
+
ActionDispatch::Routing::UrlFor
|
13
|
+
].freeze
|
14
|
+
|
15
|
+
# Attributes
|
16
|
+
|
17
|
+
attr_accessor :dictionary
|
18
|
+
|
19
|
+
def available_locales
|
20
|
+
@available_locales ||= I18n.available_locales.map(&:to_s)
|
21
|
+
end
|
22
|
+
|
23
|
+
def available_locales= locales
|
24
|
+
@available_locales = locales.map(&:to_s)
|
25
|
+
end
|
26
|
+
|
27
|
+
def default_locale
|
28
|
+
@default_locale ||= I18n.default_locale.to_s
|
29
|
+
end
|
30
|
+
|
31
|
+
def default_locale= locale
|
32
|
+
@default_locale = locale.to_s
|
33
|
+
end
|
34
|
+
|
35
|
+
def default_locale? locale
|
36
|
+
default_locale == locale.to_s
|
37
|
+
end
|
38
|
+
|
39
|
+
|
40
|
+
class << self
|
41
|
+
# Default locale suffix generator
|
42
|
+
def locale_suffix locale
|
43
|
+
locale.to_s.underscore
|
44
|
+
end
|
45
|
+
|
46
|
+
# Creates a RouteTranslator instance, using I18n dictionaries of
|
47
|
+
# your app
|
48
|
+
def init_with_i18n *wanted_locales
|
49
|
+
new.tap do |t|
|
50
|
+
t.init_i18n_dictionary *wanted_locales
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
# Creates a RouteTranslator instance and evaluates given block
|
55
|
+
# with an empty dictionary
|
56
|
+
def init_with_yield &block
|
57
|
+
new.tap do |t|
|
58
|
+
t.yield_dictionary &block
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
# Creates a RouteTranslator instance and reads the translations
|
63
|
+
# from a specified file
|
64
|
+
def init_from_file file_path
|
65
|
+
new.tap do |t|
|
66
|
+
t.load_dictionary_from_file file_path
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
module DictionaryManagement
|
72
|
+
# Resets dictionary and yields the block wich can be used to manually fill the dictionary
|
73
|
+
# with translations e.g.
|
74
|
+
# route_translator = RouteTranslator.new
|
75
|
+
# route_translator.yield_dictionary do |dict|
|
76
|
+
# dict['en'] = { 'people' => 'people' }
|
77
|
+
# dict['de'] = { 'people' => 'personen' }
|
78
|
+
# end
|
79
|
+
def yield_dictionary &block
|
80
|
+
reset_dictionary
|
81
|
+
yield @dictionary
|
82
|
+
set_available_locales_from_dictionary
|
83
|
+
end
|
84
|
+
|
85
|
+
# Resets dictionary and loads translations from specified file
|
86
|
+
# config/locales/routes.yml:
|
87
|
+
# en:
|
88
|
+
# people: people
|
89
|
+
# de:
|
90
|
+
# people: personen
|
91
|
+
# routes.rb:
|
92
|
+
# ... your routes ...
|
93
|
+
# ActionDispatch::Routing::Translator.translate_from_file
|
94
|
+
# or, to specify a custom file
|
95
|
+
# ActionDispatch::Routing::Translator.translate_from_file 'config', 'locales', 'routes.yml'
|
96
|
+
def load_dictionary_from_file file_path
|
97
|
+
reset_dictionary
|
98
|
+
add_dictionary_from_file file_path
|
99
|
+
end
|
100
|
+
|
101
|
+
# Add translations from another file to the dictionary.
|
102
|
+
def add_dictionary_from_file file_path
|
103
|
+
yaml = YAML.load_file(file_path)
|
104
|
+
yaml.each_pair do |locale, translations|
|
105
|
+
merge_translations locale, translations
|
106
|
+
end
|
107
|
+
set_available_locales_from_dictionary
|
108
|
+
end
|
109
|
+
|
110
|
+
# Merge translations for a specified locale into the dictionary
|
111
|
+
def merge_translations locale, translations
|
112
|
+
locale = locale.to_s
|
113
|
+
if translations.blank?
|
114
|
+
@dictionary[locale] ||= {}
|
115
|
+
return
|
116
|
+
end
|
117
|
+
@dictionary[locale] = (@dictionary[locale] || {}).merge(translations)
|
118
|
+
end
|
119
|
+
|
120
|
+
# Init dictionary to use I18n to translate route parts. Creates
|
121
|
+
# a hash with a block for each locale to lookup keys in I18n dynamically.
|
122
|
+
def init_i18n_dictionary *wanted_locales
|
123
|
+
wanted_locales = available_locales if wanted_locales.blank?
|
124
|
+
reset_dictionary
|
125
|
+
wanted_locales.each do |locale|
|
126
|
+
@dictionary[locale] = Hash.new do |hsh, key|
|
127
|
+
hsh[key] = I18n.translate key, :locale => locale #DISCUSS: caching or no caching (store key and translation in dictionary?)
|
128
|
+
end
|
129
|
+
end
|
130
|
+
@available_locales = @dictionary.keys.map &:to_s
|
131
|
+
end
|
132
|
+
|
133
|
+
private
|
134
|
+
def set_available_locales_from_dictionary
|
135
|
+
@available_locales = @dictionary.keys.map &:to_s
|
136
|
+
end
|
137
|
+
|
138
|
+
# Resets dictionary
|
139
|
+
def reset_dictionary
|
140
|
+
@dictionary = { default_locale => {}}
|
141
|
+
end
|
142
|
+
end
|
143
|
+
include DictionaryManagement
|
144
|
+
|
145
|
+
module Translator
|
146
|
+
# Translate a specific RouteSet, usually Rails.application.routes, but can
|
147
|
+
# be a RouteSet of a gem, plugin/engine etc.
|
148
|
+
def translate route_set
|
149
|
+
Rails.logger.info "Translating routes (default locale: #{default_locale})" if defined?(Rails) && defined?(Rails.logger)
|
150
|
+
|
151
|
+
# save original routes and clear route set
|
152
|
+
original_routes = route_set.routes.dup # Array [routeA, routeB, ...]
|
153
|
+
|
154
|
+
original_named_routes = route_set.named_routes.routes.dup # Hash {:name => :route}
|
155
|
+
|
156
|
+
reset_route_set route_set
|
157
|
+
|
158
|
+
original_routes.each do |original_route|
|
159
|
+
translations_for(original_route).each do |translated_route_args|
|
160
|
+
route_set.add_route *translated_route_args
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
original_named_routes.each_key do |route_name|
|
165
|
+
route_set.named_routes.helpers.concat add_untranslated_helpers_to_controllers_and_views(route_name)
|
166
|
+
end
|
167
|
+
|
168
|
+
end
|
169
|
+
|
170
|
+
# Add unmodified root route to route_set
|
171
|
+
def add_root_route root_route, route_set
|
172
|
+
root_route.conditions[:path_info] = root_route.conditions[:path_info].dup
|
173
|
+
route_set.set.add_route *root_route
|
174
|
+
route_set.named_routes[root_route.name] = root_route
|
175
|
+
route_set.routes << root_route
|
176
|
+
end
|
177
|
+
|
178
|
+
# Add standard route helpers for default locale e.g.
|
179
|
+
# I18n.locale = :de
|
180
|
+
# people_path -> people_de_path
|
181
|
+
# I18n.locale = :fr
|
182
|
+
# people_path -> people_fr_path
|
183
|
+
def add_untranslated_helpers_to_controllers_and_views old_name
|
184
|
+
['path', 'url'].map do |suffix|
|
185
|
+
new_helper_name = "#{old_name}_#{suffix}"
|
186
|
+
|
187
|
+
ROUTE_HELPER_CONTAINER.each do |helper_container|
|
188
|
+
helper_container.send :define_method, new_helper_name do |*args|
|
189
|
+
send "#{old_name}_#{locale_suffix(I18n.locale)}_#{suffix}", *args
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
new_helper_name.to_sym
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
# Generate translations for a single route for all available locales
|
198
|
+
def translations_for route
|
199
|
+
available_locales.map do |locale|
|
200
|
+
translate_route route, locale
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
# Generate translation for a single route for one locale
|
205
|
+
def translate_route route, locale
|
206
|
+
conditions = { :path_info => translate_path(route.path, locale) }
|
207
|
+
conditions[:request_method] = route.conditions[:request_method].source.upcase if route.conditions.has_key? :request_method
|
208
|
+
requirements = route.requirements.merge LOCALE_PARAM_KEY => locale
|
209
|
+
defaults = route.defaults.merge LOCALE_PARAM_KEY => locale
|
210
|
+
new_name = "#{route.name}_#{locale_suffix(locale)}" if route.name
|
211
|
+
|
212
|
+
[route.app, conditions, requirements, defaults, new_name]
|
213
|
+
end
|
214
|
+
|
215
|
+
# Add prefix for all non-default locales
|
216
|
+
def add_prefix? locale
|
217
|
+
!default_locale?(locale)
|
218
|
+
end
|
219
|
+
|
220
|
+
# Translates a path and adds the locale prefix.
|
221
|
+
def translate_path path, locale
|
222
|
+
final_optional_segments = path.match(/(\(.+\))$/)[1] rescue nil # i.e: (.:format)
|
223
|
+
path_segments = path.gsub(final_optional_segments,'').split("/")
|
224
|
+
new_path = path_segments.map{ |seg| translate_path_segment(seg, locale) }.join('/')
|
225
|
+
new_path = "/#{locale.downcase}#{new_path}" if add_prefix? locale
|
226
|
+
new_path = '/' if new_path.blank?
|
227
|
+
final_optional_segments ? new_path + final_optional_segments : new_path
|
228
|
+
end
|
229
|
+
|
230
|
+
# Tries to translate a single path segment. If the path segment
|
231
|
+
# contains sth. like a optional format "people(.:format)", only
|
232
|
+
# "people" will be translated, if there is no translation, the path
|
233
|
+
# segment is blank or begins with a ":" (param key), the segment
|
234
|
+
# is returned untouched
|
235
|
+
def translate_path_segment segment, locale
|
236
|
+
return segment if segment.blank? or segment.starts_with?(":")
|
237
|
+
|
238
|
+
match = TRANSLATABLE_SEGMENT.match(segment)[1] rescue nil
|
239
|
+
|
240
|
+
(translate_string(match, locale) || segment).downcase
|
241
|
+
end
|
242
|
+
|
243
|
+
def translate_string str, locale
|
244
|
+
@dictionary[locale.to_s][str.to_s]
|
245
|
+
end
|
246
|
+
|
247
|
+
private
|
248
|
+
def reset_route_set route_set
|
249
|
+
route_set.clear!
|
250
|
+
remove_all_methods_in route_set.named_routes.module
|
251
|
+
end
|
252
|
+
|
253
|
+
def remove_all_methods_in mod
|
254
|
+
mod.instance_methods.each do |method|
|
255
|
+
mod.send :remove_method, method
|
256
|
+
end
|
257
|
+
end
|
258
|
+
end
|
259
|
+
include Translator
|
260
|
+
|
261
|
+
def locale_suffix locale
|
262
|
+
self.class.locale_suffix locale
|
263
|
+
end
|
264
|
+
end
|
265
|
+
|
266
|
+
# Adapter for Rails 3 Apps
|
267
|
+
module ActionDispatch
|
268
|
+
module Routing
|
269
|
+
module Translator
|
270
|
+
class << self
|
271
|
+
def translate &block
|
272
|
+
RouteTranslator.init_with_yield(&block).translate Rails.application.routes
|
273
|
+
end
|
274
|
+
|
275
|
+
def translate_from_file *file_path
|
276
|
+
file_path = %w(config locales routes.yml) if file_path.blank?
|
277
|
+
RouteTranslator.init_from_file(File.join(Rails.root, *file_path)).translate Rails.application.routes
|
278
|
+
end
|
279
|
+
|
280
|
+
def i18n *locales
|
281
|
+
RouteTranslator.init_with_i18n(*locales).translate Rails.application.routes
|
282
|
+
end
|
283
|
+
end
|
284
|
+
end
|
285
|
+
end
|
286
|
+
end
|
287
|
+
|
288
|
+
# Add set_locale_from_url to controllers
|
289
|
+
ActionController::Base.class_eval do
|
290
|
+
private
|
291
|
+
# called by before_filter
|
292
|
+
def set_locale_from_url
|
293
|
+
I18n.locale = params[RouteTranslator::LOCALE_PARAM_KEY]
|
294
|
+
default_url_options.merge! RouteTranslator::LOCALE_PARAM_KEY => I18n.locale
|
295
|
+
end
|
296
|
+
end
|
297
|
+
|
298
|
+
# Add locale_suffix to controllers, views and mailers
|
299
|
+
RouteTranslator::ROUTE_HELPER_CONTAINER.each do |klass|
|
300
|
+
klass.class_eval do
|
301
|
+
private
|
302
|
+
def locale_suffix locale
|
303
|
+
RouteTranslator.locale_suffix locale
|
304
|
+
end
|
305
|
+
end
|
306
|
+
end
|
data/lib/translate_routes.rb
CHANGED
@@ -1,219 +1 @@
|
|
1
|
-
|
2
|
-
# Copyright (c) 2007, Released under the MIT license (see MIT-LICENSE)
|
3
|
-
|
4
|
-
module ActionController
|
5
|
-
|
6
|
-
module Routing
|
7
|
-
|
8
|
-
module Translator
|
9
|
-
|
10
|
-
mattr_accessor :prefix_on_default_locale
|
11
|
-
@@prefix_on_default_locale = false
|
12
|
-
|
13
|
-
mattr_accessor :locale_param_key
|
14
|
-
@@locale_param_key = :locale # set to :locale for params[:locale]
|
15
|
-
|
16
|
-
mattr_accessor :original_routes, :original_named_routes, :original_names, :dictionaries
|
17
|
-
|
18
|
-
def self.translate
|
19
|
-
init_dictionaries
|
20
|
-
yield @@dictionaries
|
21
|
-
@using_i18n = false
|
22
|
-
Translator.translate_current_routes
|
23
|
-
end
|
24
|
-
|
25
|
-
def self.translate_from_file(*path)
|
26
|
-
init_dictionaries
|
27
|
-
path = %w(locales routes.yml) if path.blank?
|
28
|
-
file_path = File.join(RAILS_ROOT, path)
|
29
|
-
yaml = YAML.load_file(file_path)
|
30
|
-
yaml.each_pair{ |k,v| @@dictionaries[k.to_s] = v || {} }
|
31
|
-
@using_i18n = false
|
32
|
-
Translator.translate_current_routes
|
33
|
-
end
|
34
|
-
|
35
|
-
def self.i18n(*locales)
|
36
|
-
init_dictionaries
|
37
|
-
locales = I18n.available_locales if locales.blank? && I18n.respond_to?(:available_locales)
|
38
|
-
locales.each{ |locale| @@dictionaries[locale] = {} }
|
39
|
-
@using_i18n = true
|
40
|
-
Translator.translate_current_routes
|
41
|
-
end
|
42
|
-
|
43
|
-
private
|
44
|
-
|
45
|
-
def self.default_locale
|
46
|
-
I18n.default_locale.to_s
|
47
|
-
end
|
48
|
-
|
49
|
-
def self.init_dictionaries
|
50
|
-
@@dictionaries = { default_locale => {} }
|
51
|
-
end
|
52
|
-
|
53
|
-
def self.available_locales
|
54
|
-
@@dictionaries.keys.map(&:to_s).uniq
|
55
|
-
end
|
56
|
-
|
57
|
-
def self.original_static_segments
|
58
|
-
static_segments = []
|
59
|
-
(@@original_routes || Routes.routes).each do |r|
|
60
|
-
r.segments.select do |s|
|
61
|
-
static_segments << s.value if s.instance_of?(ActionController::Routing::StaticSegment)
|
62
|
-
end
|
63
|
-
end
|
64
|
-
static_segments.uniq.sort
|
65
|
-
end
|
66
|
-
|
67
|
-
# code shared by translation and application helpers,
|
68
|
-
# it generates a suffix code for a given locale: en-US -> en_us
|
69
|
-
def self.locale_suffix_code
|
70
|
-
'locale.to_s.underscore'
|
71
|
-
end
|
72
|
-
|
73
|
-
class_eval <<-FOO
|
74
|
-
def self.locale_suffix(locale)
|
75
|
-
#{self.locale_suffix_code}
|
76
|
-
end
|
77
|
-
FOO
|
78
|
-
def self.translate_current_routes
|
79
|
-
|
80
|
-
RAILS_DEFAULT_LOGGER.info "Translating routes (default locale: #{default_locale})" if defined? RAILS_DEFAULT_LOGGER
|
81
|
-
|
82
|
-
@@original_routes = Routes.routes.dup # Array [routeA, routeB, ...]
|
83
|
-
@@original_named_routes = Routes.named_routes.routes.dup # Hash {:name => :route}
|
84
|
-
@@original_names = @@original_named_routes.keys
|
85
|
-
|
86
|
-
Routes.clear!
|
87
|
-
new_routes = []
|
88
|
-
new_named_routes = {}
|
89
|
-
|
90
|
-
@@original_routes.each do |old_route|
|
91
|
-
|
92
|
-
old_name = @@original_named_routes.index(old_route)
|
93
|
-
# process and add the translated ones
|
94
|
-
trans_routes, trans_named_routes = translate_route(old_route, old_name)
|
95
|
-
|
96
|
-
if old_name
|
97
|
-
new_named_routes.merge! trans_named_routes
|
98
|
-
end
|
99
|
-
|
100
|
-
new_routes.concat(trans_routes)
|
101
|
-
|
102
|
-
end
|
103
|
-
|
104
|
-
Routes.routes = new_routes
|
105
|
-
new_named_routes.each { |name, r| Routes.named_routes.add name, r }
|
106
|
-
|
107
|
-
@@original_names.each{ |old_name| add_untranslated_helpers_to_controllers_and_views(old_name) }
|
108
|
-
end
|
109
|
-
|
110
|
-
# The untranslated helper (root_path instead root_en_path) redirects according to the current locale
|
111
|
-
def self.add_untranslated_helpers_to_controllers_and_views(old_name)
|
112
|
-
|
113
|
-
['path', 'url'].each do |suffix|
|
114
|
-
new_helper_name = "#{old_name}_#{suffix}"
|
115
|
-
def_new_helper = <<-DEF_NEW_HELPER
|
116
|
-
def #{new_helper_name}(*args)
|
117
|
-
send("#{old_name}_\#{locale_suffix(I18n.locale)}_#{suffix}", *args)
|
118
|
-
end
|
119
|
-
DEF_NEW_HELPER
|
120
|
-
|
121
|
-
[ActionController::Base, ActionView::Base, ActionMailer::Base].each { |d| d.module_eval(def_new_helper) }
|
122
|
-
ActionController::Routing::Routes.named_routes.helpers << new_helper_name.to_sym
|
123
|
-
end
|
124
|
-
end
|
125
|
-
|
126
|
-
def self.add_prefix?(lang)
|
127
|
-
@@prefix_on_default_locale || lang != default_locale
|
128
|
-
end
|
129
|
-
|
130
|
-
def self.translate_static_segment(segment, locale)
|
131
|
-
if @using_i18n
|
132
|
-
tmp = I18n.locale
|
133
|
-
I18n.locale = locale
|
134
|
-
value = I18n.t segment.value, :default => segment.value.dup
|
135
|
-
I18n.locale = tmp
|
136
|
-
else
|
137
|
-
value = @@dictionaries[locale][segment.value] || segment.value.dup
|
138
|
-
end
|
139
|
-
StaticSegment.new(value, :raw => segment.raw, :optional => segment.optional?)
|
140
|
-
end
|
141
|
-
|
142
|
-
def self.locale_segments(orig, locale)
|
143
|
-
segments = []
|
144
|
-
|
145
|
-
if add_prefix?(locale) # initial prefix i.e: /en-US
|
146
|
-
divider = DividerSegment.new(orig.segments.first.value, :optional => false) # divider ('/')
|
147
|
-
static = StaticSegment.new(locale, :optional => false) # static ('en-US')
|
148
|
-
segments += [divider, static]
|
149
|
-
end
|
150
|
-
|
151
|
-
orig.segments.each do |s|
|
152
|
-
if s.instance_of?(StaticSegment)
|
153
|
-
new_segment = translate_static_segment(s, locale)
|
154
|
-
else
|
155
|
-
new_segment = s.dup # just reference the original
|
156
|
-
end
|
157
|
-
segments << new_segment
|
158
|
-
end
|
159
|
-
segments
|
160
|
-
end
|
161
|
-
|
162
|
-
def self.locale_requirements(orig, locale)
|
163
|
-
orig.requirements.merge(@@locale_param_key => locale)
|
164
|
-
end
|
165
|
-
|
166
|
-
def self.translate_route_by_locale(orig, locale, orig_name=nil)
|
167
|
-
segments = locale_segments(orig, locale)
|
168
|
-
requirements = locale_requirements(orig, locale)
|
169
|
-
conditions = orig.conditions
|
170
|
-
|
171
|
-
Route.new(segments, requirements, conditions).freeze
|
172
|
-
end
|
173
|
-
|
174
|
-
def self.root_route?(route)
|
175
|
-
route.segments.length == 1
|
176
|
-
end
|
177
|
-
|
178
|
-
def self.translate_route(route, route_name = nil)
|
179
|
-
new_routes = []
|
180
|
-
new_named_routes = {}
|
181
|
-
|
182
|
-
if root_route?(route) && prefix_on_default_locale
|
183
|
-
# add the root route "as is" in addition to the translated versions
|
184
|
-
new_routes << route
|
185
|
-
new_named_routes[route_name] = route
|
186
|
-
end
|
187
|
-
|
188
|
-
available_locales.each do |locale|
|
189
|
-
translated = translate_route_by_locale(route, locale, route_name)
|
190
|
-
new_routes << translated
|
191
|
-
locale_suffix = locale_suffix(locale)
|
192
|
-
new_named_routes["#{route_name}_#{locale_suffix}".to_sym] = translated if route_name
|
193
|
-
end
|
194
|
-
[new_routes, new_named_routes]
|
195
|
-
end
|
196
|
-
|
197
|
-
end
|
198
|
-
|
199
|
-
end
|
200
|
-
end
|
201
|
-
|
202
|
-
# Add set_locale_from_url to controllers
|
203
|
-
ActionController::Base.class_eval do
|
204
|
-
private
|
205
|
-
def set_locale_from_url
|
206
|
-
I18n.locale = params[ActionController::Routing::Translator.locale_param_key]
|
207
|
-
default_url_options({ActionController::Routing::Translator => I18n.locale })
|
208
|
-
end
|
209
|
-
end
|
210
|
-
|
211
|
-
# Add locale_suffix to controllers, views and mailers
|
212
|
-
[ActionController::Base, ActionView::Base, ActionMailer::Base].map do |klass|
|
213
|
-
klass.class_eval do
|
214
|
-
private
|
215
|
-
def locale_suffix(locale)
|
216
|
-
eval ActionController::Routing::Translator.locale_suffix_code
|
217
|
-
end
|
218
|
-
end
|
219
|
-
end
|
1
|
+
require 'route_translator'
|
@@ -1,10 +1,10 @@
|
|
1
1
|
# Author: Raul Murciano [http://raul.murciano.net] for Domestika [http://domestika.org]
|
2
2
|
# Copyright (c) 2007, Released under the MIT license (see MIT-LICENSE)
|
3
3
|
|
4
|
-
require 'test_help'
|
4
|
+
require 'rails/test_help'
|
5
5
|
|
6
6
|
# Include default lang on your test requests (test requests doesn't support default_url_options):
|
7
|
-
ActionController::
|
7
|
+
ActionController::TestCase.class_eval do
|
8
8
|
unless method_defined?(:process_without_default_language)
|
9
9
|
def process_with_default_language(action, parameters = nil, session = nil, flash = nil, http_method = 'GET')
|
10
10
|
lang_pair = {:locale, I18n.default_locale.to_s}
|
@@ -20,11 +20,11 @@ end
|
|
20
20
|
# Add untranslated helper for named routes to integration tests
|
21
21
|
ActionController::Integration::Session.class_eval do
|
22
22
|
['path', 'url'].each do |suffix|
|
23
|
-
|
23
|
+
ActionDispatch::Routing::Translator.original_names.each do |old_name|
|
24
24
|
new_helper_name = "#{old_name}_#{suffix}"
|
25
25
|
def_new_helper = <<-DEF_NEW_HELPER
|
26
26
|
def #{new_helper_name}(*args)
|
27
|
-
send("#{old_name}_#{
|
27
|
+
send("#{old_name}_#{ActionDispatch::Routing::Translator.locale_suffix(I18n.locale)}_#{suffix}", *args)
|
28
28
|
end
|
29
29
|
DEF_NEW_HELPER
|
30
30
|
eval def_new_helper
|
@@ -1,181 +1,103 @@
|
|
1
1
|
require 'test/unit'
|
2
2
|
require 'rubygems'
|
3
|
+
require 'mocha'
|
3
4
|
|
4
|
-
%w(actionpack activesupport actionmailer).each{ |gem_lib| gem gem_lib, '
|
5
|
-
%w(
|
5
|
+
%w(actionpack activesupport actionmailer).each{ |gem_lib| gem gem_lib, '3.0.1' }
|
6
|
+
%w(active_support action_pack action_mailer action_controller action_dispatch).each{ |lib| require lib }
|
6
7
|
|
7
8
|
plugin_root = File.join(File.dirname(__FILE__), '..')
|
8
|
-
require "#{plugin_root}/lib/
|
9
|
-
|
9
|
+
require "#{plugin_root}/lib/route_translator"
|
10
|
+
|
10
11
|
|
11
12
|
class PeopleController < ActionController::Base; end
|
12
13
|
|
13
14
|
class TranslateRoutesTest < ActionController::TestCase
|
15
|
+
include ActionDispatch::Assertions::RoutingAssertions
|
14
16
|
|
15
|
-
|
17
|
+
def config_default_locale_settings(locale)
|
18
|
+
I18n.default_locale = locale
|
19
|
+
end
|
20
|
+
|
21
|
+
def translate_routes
|
22
|
+
@route_translator.translate @routes
|
23
|
+
@routes.finalize!
|
24
|
+
@routes.named_routes.install
|
25
|
+
end
|
16
26
|
|
17
27
|
def setup
|
18
28
|
@controller = ActionController::Base.new
|
19
29
|
@view = ActionView::Base.new
|
20
|
-
|
30
|
+
@routes = ActionDispatch::Routing::RouteSet.new
|
31
|
+
@route_translator = RouteTranslator.new
|
21
32
|
end
|
22
33
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
config_default_locale_settings('en', true)
|
29
|
-
ActionController::Routing::Translator.translate { |t| t['en'] = {}; t['es'] = {'people' => 'gente'} }
|
30
|
-
|
31
|
-
assert_routing '/es', :controller => 'people', :action => 'index', :locale => 'es'
|
32
|
-
assert_routing '/en', :controller => 'people', :action => 'index', :locale => 'en'
|
33
|
-
end
|
34
|
-
|
35
|
-
def test_unnamed_root_route_with_prefix
|
36
|
-
ActionController::Routing::Routes.draw { |map| map.connect '/', :controller => 'people', :action => 'index'}
|
37
|
-
config_default_locale_settings('es', true)
|
38
|
-
ActionController::Routing::Translator.translate_from_file 'test', 'locales', 'routes.yml'
|
39
|
-
|
40
|
-
assert_routing '/', :controller => 'people', :action => 'index'
|
41
|
-
assert_routing '/es', :controller => 'people', :action => 'index', :locale => 'es'
|
42
|
-
assert_routing '/en', :controller => 'people', :action => 'index', :locale => 'en'
|
43
|
-
end
|
44
|
-
|
45
|
-
def test_unnamed_untranslated_route_with_prefix
|
46
|
-
ActionController::Routing::Routes.draw { |map| map.connect 'foo', :controller => 'people', :action => 'index' }
|
47
|
-
config_default_locale_settings('en', true)
|
48
|
-
ActionController::Routing::Translator.translate { |t| t['en'] = {}; t['es'] = {'people' => 'gente'} }
|
49
|
-
|
50
|
-
assert_routing '/es/foo', :controller => 'people', :action => 'index', :locale => 'es'
|
51
|
-
assert_routing '/en/foo', :controller => 'people', :action => 'index', :locale => 'en'
|
52
|
-
end
|
53
|
-
|
54
|
-
def test_unnamed_translated_route_on_default_locale_with_prefix
|
55
|
-
ActionController::Routing::Routes.draw { |map| map.people 'people', :controller => 'people', :action => 'index'}
|
56
|
-
config_default_locale_settings('es', true)
|
57
|
-
ActionController::Routing::Translator.translate { |t| t['en'] = {}; t['es'] = {'people' => 'gente'} }
|
58
|
-
|
59
|
-
assert_routing '/es/gente', :controller => 'people', :action => 'index', :locale => 'es'
|
60
|
-
end
|
61
|
-
|
62
|
-
def test_unnamed_translated_route_on_non_default_locale_with_prefix
|
63
|
-
ActionController::Routing::Routes.draw { |map| map.connect 'people', :controller => 'people', :action => 'index' }
|
64
|
-
config_default_locale_settings('en', true)
|
65
|
-
ActionController::Routing::Translator.translate { |t| t['en'] = {}; t['es'] = {'people' => 'gente'} }
|
34
|
+
def test_unnamed_root_route
|
35
|
+
@routes.draw { root :to => 'people#index' }
|
36
|
+
config_default_locale_settings 'en'
|
37
|
+
@route_translator.yield_dictionary { |t| t['en'] = {}; t['es'] = {'people' => 'gente'} }
|
38
|
+
translate_routes
|
66
39
|
|
67
|
-
assert_routing '/es/gente', :controller => 'people', :action => 'index', :locale => 'es'
|
68
|
-
assert_routing '/en/people', :controller => 'people', :action => 'index', :locale => 'en'
|
69
|
-
end
|
70
|
-
|
71
|
-
|
72
|
-
# Unnamed routes without prefix on default locale:
|
73
|
-
|
74
|
-
def test_unnamed_empty_route_without_prefix
|
75
|
-
ActionController::Routing::Routes.draw { |map| map.connect '', :controller => 'people', :action => 'index' }
|
76
|
-
config_default_locale_settings('en', false)
|
77
|
-
ActionController::Routing::Translator.translate { |t| t['en'] = {}; t['es'] = {'people' => 'gente'} }
|
78
|
-
|
79
|
-
assert_routing '/es', :controller => 'people', :action => 'index', :locale => 'es'
|
80
40
|
assert_routing '/', :controller => 'people', :action => 'index', :locale => 'en'
|
41
|
+
assert_routing '/es', :controller => 'people', :action => 'index', :locale => 'es'
|
81
42
|
end
|
82
43
|
|
83
44
|
def test_unnamed_root_route_without_prefix
|
84
|
-
|
85
|
-
config_default_locale_settings
|
86
|
-
|
45
|
+
@routes.draw { root :to => 'people#index' }
|
46
|
+
config_default_locale_settings 'es'
|
47
|
+
@route_translator.load_dictionary_from_file File.expand_path('locales/routes.yml', File.dirname(__FILE__))
|
48
|
+
translate_routes
|
87
49
|
|
88
50
|
assert_routing '/', :controller => 'people', :action => 'index', :locale => 'es'
|
89
51
|
assert_routing '/en', :controller => 'people', :action => 'index', :locale => 'en'
|
90
52
|
assert_unrecognized_route '/es', :controller => 'people', :action => 'index', :locale => 'es'
|
91
53
|
end
|
92
54
|
|
93
|
-
def
|
94
|
-
|
95
|
-
config_default_locale_settings
|
96
|
-
|
97
|
-
|
55
|
+
def test_unnamed_untranslated_route
|
56
|
+
@routes.draw { match 'foo', :to => 'people#index' }
|
57
|
+
config_default_locale_settings 'en'
|
58
|
+
@route_translator.yield_dictionary { |t| t['en'] = {}; t['es'] = {'people' => 'gente'} }
|
59
|
+
translate_routes
|
60
|
+
|
98
61
|
assert_routing '/es/foo', :controller => 'people', :action => 'index', :locale => 'es'
|
99
62
|
assert_routing '/foo', :controller => 'people', :action => 'index', :locale => 'en'
|
100
63
|
end
|
101
64
|
|
102
|
-
def
|
103
|
-
|
104
|
-
config_default_locale_settings
|
105
|
-
|
65
|
+
def test_unnamed_translated_route_on_default_locale
|
66
|
+
@routes.draw { match 'people', :to => 'people#index' }
|
67
|
+
config_default_locale_settings 'es'
|
68
|
+
@route_translator.yield_dictionary { |t| t['en'] = {}; t['es'] = {'people' => 'gente'} }
|
69
|
+
translate_routes
|
106
70
|
|
107
71
|
assert_routing '/en/people', :controller => 'people', :action => 'index', :locale => 'en'
|
108
|
-
assert_routing 'gente', :controller => 'people', :action => 'index', :locale => 'es'
|
72
|
+
assert_routing '/gente', :controller => 'people', :action => 'index', :locale => 'es'
|
109
73
|
end
|
110
74
|
|
111
|
-
def
|
112
|
-
|
113
|
-
config_default_locale_settings
|
114
|
-
|
75
|
+
def test_unnamed_translated_route_on_non_default_locale
|
76
|
+
@routes.draw { match 'people', :to => 'people#index' }
|
77
|
+
config_default_locale_settings 'en'
|
78
|
+
@route_translator.yield_dictionary { |t| t['en'] = {}; t['es'] = {'people' => 'gente'} }
|
79
|
+
translate_routes
|
115
80
|
|
116
81
|
assert_routing '/es/gente', :controller => 'people', :action => 'index', :locale => 'es'
|
117
82
|
assert_routing '/people', :controller => 'people', :action => 'index', :locale => 'en'
|
118
83
|
end
|
119
84
|
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
assert_routing '/en', :controller => 'people', :action => 'index', :locale => 'en'
|
130
|
-
assert_helpers_include :people_en, :people_es, :people
|
131
|
-
end
|
132
|
-
|
133
|
-
def test_named_root_route_with_prefix
|
134
|
-
ActionController::Routing::Routes.draw { |map| map.root :controller => 'people', :action => 'index'}
|
135
|
-
config_default_locale_settings('es', true)
|
136
|
-
ActionController::Routing::Translator.translate_from_file 'test', 'locales', 'routes.yml'
|
137
|
-
|
138
|
-
assert_routing '/', :controller => 'people', :action => 'index'
|
139
|
-
assert_routing '/es', :controller => 'people', :action => 'index', :locale => 'es'
|
140
|
-
assert_routing '/en', :controller => 'people', :action => 'index', :locale => 'en'
|
141
|
-
end
|
142
|
-
|
143
|
-
def test_named_untranslated_route_with_prefix
|
144
|
-
ActionController::Routing::Routes.draw { |map| map.people 'foo', :controller => 'people', :action => 'index'}
|
145
|
-
config_default_locale_settings('en', true)
|
146
|
-
ActionController::Routing::Translator.translate { |t| t['en'] = {}; t['es'] = {'people' => 'gente'} }
|
147
|
-
|
148
|
-
assert_routing '/es/foo', :controller => 'people', :action => 'index', :locale => 'es'
|
149
|
-
assert_routing '/en/foo', :controller => 'people', :action => 'index', :locale => 'en'
|
150
|
-
assert_helpers_include :people_en, :people_es, :people
|
151
|
-
end
|
152
|
-
|
153
|
-
def test_named_translated_route_on_default_locale_with_prefix
|
154
|
-
ActionController::Routing::Routes.draw { |map| map.people 'people', :controller => 'people', :action => 'index'}
|
155
|
-
config_default_locale_settings('es', true)
|
156
|
-
ActionController::Routing::Translator.translate { |t| t['en'] = {}; t['es'] = {'people' => 'gente'} }
|
157
|
-
|
158
|
-
assert_routing '/en/people', :controller => 'people', :action => 'index', :locale => 'en'
|
159
|
-
assert_routing '/es/gente', :controller => 'people', :action => 'index', :locale => 'es'
|
160
|
-
assert_helpers_include :people_en, :people_es, :people
|
161
|
-
end
|
162
|
-
|
163
|
-
def test_named_translated_route_on_non_default_locale_with_prefix
|
164
|
-
ActionController::Routing::Routes.draw { |map| map.people 'people', :controller => 'people', :action => 'index' }
|
165
|
-
config_default_locale_settings('en', true)
|
166
|
-
ActionController::Routing::Translator.translate { |t| t['en'] = {}; t['es'] = {'people' => 'gente'} }
|
167
|
-
|
168
|
-
assert_routing '/es/gente', :controller => 'people', :action => 'index', :locale => 'es'
|
169
|
-
assert_routing '/en/people', :controller => 'people', :action => 'index', :locale => 'en'
|
170
|
-
assert_helpers_include :people_en, :people_es, :people
|
85
|
+
def test_named_translated_route_with_prefix_must_have_locale_as_static_segment
|
86
|
+
@routes.draw { match 'people', :to => 'people#index', :as => 'people' }
|
87
|
+
config_default_locale_settings 'en'
|
88
|
+
@route_translator.yield_dictionary { |t| t['en'] = {}; t['es'] = {'people' => 'gente'} }
|
89
|
+
translate_routes
|
90
|
+
|
91
|
+
# we check the string representation of the route,
|
92
|
+
# if it stores locale as a dynamic segment it would be represented as: "/:locale/gente"
|
93
|
+
assert_equal "/es/gente(.:format)", path_string(named_route('people_es'))
|
171
94
|
end
|
172
95
|
|
173
|
-
# Named routes without prefix on default locale:
|
174
|
-
|
175
96
|
def test_named_empty_route_without_prefix
|
176
|
-
|
177
|
-
config_default_locale_settings
|
178
|
-
|
97
|
+
@routes.draw { root :to => 'people#index', :as => 'people' }
|
98
|
+
config_default_locale_settings 'es'
|
99
|
+
@route_translator.yield_dictionary { |t| t['es'] = {}; t['en'] = {'people' => 'gente'}; }
|
100
|
+
translate_routes
|
179
101
|
|
180
102
|
assert_routing '/en', :controller => 'people', :action => 'index', :locale => 'en'
|
181
103
|
assert_routing '/', :controller => 'people', :action => 'index', :locale => 'es'
|
@@ -183,9 +105,10 @@ class TranslateRoutesTest < ActionController::TestCase
|
|
183
105
|
end
|
184
106
|
|
185
107
|
def test_named_root_route_without_prefix
|
186
|
-
|
187
|
-
config_default_locale_settings
|
188
|
-
|
108
|
+
@routes.draw { root :to => 'people#index' }
|
109
|
+
config_default_locale_settings 'es'
|
110
|
+
@route_translator.load_dictionary_from_file File.expand_path('locales/routes.yml', File.dirname(__FILE__))
|
111
|
+
translate_routes
|
189
112
|
|
190
113
|
assert_routing '/', :controller => 'people', :action => 'index', :locale => 'es'
|
191
114
|
assert_routing '/en', :controller => 'people', :action => 'index', :locale => 'en'
|
@@ -193,9 +116,10 @@ class TranslateRoutesTest < ActionController::TestCase
|
|
193
116
|
end
|
194
117
|
|
195
118
|
def test_named_untranslated_route_without_prefix
|
196
|
-
|
197
|
-
config_default_locale_settings
|
198
|
-
|
119
|
+
@routes.draw { match 'foo', :to => 'people#index', :as => 'people' }
|
120
|
+
config_default_locale_settings 'es'
|
121
|
+
@route_translator.yield_dictionary { |t| t['en'] = {}; t['es'] = {'people' => 'gente'} }
|
122
|
+
translate_routes
|
199
123
|
|
200
124
|
assert_routing '/en/foo', :controller => 'people', :action => 'index', :locale => 'en'
|
201
125
|
assert_routing 'foo', :controller => 'people', :action => 'index', :locale => 'es'
|
@@ -203,9 +127,10 @@ class TranslateRoutesTest < ActionController::TestCase
|
|
203
127
|
end
|
204
128
|
|
205
129
|
def test_named_translated_route_on_default_locale_without_prefix
|
206
|
-
|
207
|
-
config_default_locale_settings
|
208
|
-
|
130
|
+
@routes.draw { match 'people', :to => 'people#index', :as => 'people'}
|
131
|
+
config_default_locale_settings 'es'
|
132
|
+
@route_translator.yield_dictionary { |t| t['en'] = {}; t['es'] = {'people' => 'gente'} }
|
133
|
+
translate_routes
|
209
134
|
|
210
135
|
assert_routing '/en/people', :controller => 'people', :action => 'index', :locale => 'en'
|
211
136
|
assert_routing 'gente', :controller => 'people', :action => 'index', :locale => 'es'
|
@@ -213,30 +138,58 @@ class TranslateRoutesTest < ActionController::TestCase
|
|
213
138
|
end
|
214
139
|
|
215
140
|
def test_named_translated_route_on_non_default_locale_without_prefix
|
216
|
-
|
217
|
-
config_default_locale_settings
|
218
|
-
|
141
|
+
@routes.draw { match 'people', :to => 'people#index', :as => 'people'}
|
142
|
+
config_default_locale_settings 'en'
|
143
|
+
@route_translator.yield_dictionary { |t| t['en'] = {}; t['es'] = {'people' => 'gente'} }
|
144
|
+
translate_routes
|
219
145
|
|
220
146
|
assert_routing '/people', :controller => 'people', :action => 'index', :locale => 'en'
|
221
147
|
assert_routing '/es/gente', :controller => 'people', :action => 'index', :locale => 'es'
|
222
148
|
assert_helpers_include :people_en, :people_es, :people
|
223
149
|
end
|
150
|
+
|
151
|
+
def test_formatted_root_route
|
152
|
+
@routes.draw{ root :to => 'people#index', :as => 'root' }
|
153
|
+
@route_translator.yield_dictionary { |t| t['en'] = {}; t['es'] = {'people' => 'gente'} }
|
154
|
+
assert_equal '/(.:format)', path_string(named_route('root'))
|
155
|
+
translate_routes
|
156
|
+
assert_equal '/(.:format)', path_string(named_route('root_en'))
|
157
|
+
assert_equal '/es(.:format)', path_string(named_route('root_es'))
|
158
|
+
end
|
159
|
+
|
160
|
+
def test_routes_translations_are_always_downcased
|
161
|
+
@routes.draw { match 'people', :to => 'people#index', :as => 'people'}
|
162
|
+
config_default_locale_settings 'en'
|
163
|
+
@route_translator.yield_dictionary { |t| t['en'] = {}; t['es'] = {'people' => 'Gente'} }
|
164
|
+
translate_routes
|
165
|
+
assert_routing '/es/gente', :controller => 'people', :action => 'index', :locale => 'es'
|
166
|
+
end
|
167
|
+
|
168
|
+
def test_routes_locale_prefixes_are_always_downcased
|
169
|
+
@routes.draw { match 'people', :to => 'people#index', :as => 'people'}
|
170
|
+
config_default_locale_settings 'en'
|
171
|
+
@route_translator.yield_dictionary { |t| t['en'] = {}; t['ES'] = {'people' => 'Gente'} }
|
172
|
+
translate_routes
|
173
|
+
assert_routing '/es/gente', :controller => 'people', :action => 'index', :locale => 'ES'
|
174
|
+
end
|
224
175
|
|
225
176
|
def test_languages_load_from_file
|
226
|
-
|
227
|
-
config_default_locale_settings
|
228
|
-
|
229
|
-
|
177
|
+
@routes.draw { match 'people', :to => 'people#index', :as => 'people'}
|
178
|
+
config_default_locale_settings 'en'
|
179
|
+
@route_translator.load_dictionary_from_file File.expand_path('locales/routes.yml', File.dirname(__FILE__))
|
180
|
+
translate_routes
|
181
|
+
|
230
182
|
assert_routing '/people', :controller => 'people', :action => 'index', :locale => 'en'
|
231
183
|
assert_routing '/es/gente', :controller => 'people', :action => 'index', :locale => 'es'
|
232
184
|
assert_helpers_include :people_en, :people_es, :people
|
233
185
|
end
|
234
186
|
|
235
187
|
def test_languages_load_from_file_without_dictionary_for_default_locale
|
236
|
-
|
237
|
-
config_default_locale_settings
|
238
|
-
|
239
|
-
|
188
|
+
@routes.draw { match 'people', :to => 'people#index', :as => 'people'}
|
189
|
+
config_default_locale_settings 'fr'
|
190
|
+
@route_translator.load_dictionary_from_file File.expand_path('locales/routes.yml', File.dirname(__FILE__))
|
191
|
+
translate_routes
|
192
|
+
|
240
193
|
assert_routing '/people', :controller => 'people', :action => 'index', :locale => 'fr'
|
241
194
|
assert_routing '/en/people', :controller => 'people', :action => 'index', :locale => 'en'
|
242
195
|
assert_routing '/es/gente', :controller => 'people', :action => 'index', :locale => 'es'
|
@@ -244,26 +197,28 @@ class TranslateRoutesTest < ActionController::TestCase
|
|
244
197
|
end
|
245
198
|
|
246
199
|
def test_i18n_based_translations_setting_locales
|
247
|
-
|
248
|
-
config_default_locale_settings
|
200
|
+
@routes.draw { match 'people', :to => 'people#index', :as => 'people'}
|
201
|
+
config_default_locale_settings 'en'
|
249
202
|
I18n.backend = StubbedI18nBackend
|
250
|
-
|
203
|
+
@route_translator.init_i18n_dictionary 'es'
|
204
|
+
translate_routes
|
251
205
|
|
252
|
-
assert_routing '/people', :controller => 'people', :action => 'index', :locale => 'en'
|
253
206
|
assert_routing '/es/gente', :controller => 'people', :action => 'index', :locale => 'es'
|
207
|
+
assert_routing '/people', :controller => 'people', :action => 'index', :locale => 'en'
|
254
208
|
assert_helpers_include :people_en, :people_es, :people
|
255
209
|
end
|
256
210
|
|
257
211
|
def test_i18n_based_translations_taking_i18n_available_locales
|
258
|
-
|
259
|
-
config_default_locale_settings
|
212
|
+
@routes.draw { match 'people', :to => 'people#index', :as => 'people'}
|
213
|
+
config_default_locale_settings 'en'
|
260
214
|
I18n.stubs(:available_locales).at_least_once.returns StubbedI18nBackend.available_locales
|
261
215
|
I18n.backend = StubbedI18nBackend
|
262
|
-
|
216
|
+
@route_translator.init_i18n_dictionary
|
217
|
+
translate_routes
|
263
218
|
|
264
|
-
assert_routing '/people', :controller => 'people', :action => 'index', :locale => 'en'
|
265
219
|
assert_routing '/fr/people', :controller => 'people', :action => 'index', :locale => 'fr'
|
266
220
|
assert_routing '/es/gente', :controller => 'people', :action => 'index', :locale => 'es'
|
221
|
+
assert_routing '/people', :controller => 'people', :action => 'index', :locale => 'en'
|
267
222
|
assert_helpers_include :people_fr, :people_en, :people_es, :people
|
268
223
|
end
|
269
224
|
|
@@ -280,44 +235,50 @@ class TranslateRoutesTest < ActionController::TestCase
|
|
280
235
|
end
|
281
236
|
|
282
237
|
private
|
283
|
-
|
238
|
+
|
239
|
+
# Given a route defined as a string like this:
|
240
|
+
# 'ANY /es(.:format) {:controller=>"people", :action=>"index"}'
|
241
|
+
# returns "/es(.:format)"
|
242
|
+
def path_string(route)
|
243
|
+
route.to_s.split(' ')[1]
|
244
|
+
end
|
245
|
+
|
246
|
+
def named_route(name)
|
247
|
+
@routes.routes.select{ |r| r.name == name }.first
|
248
|
+
end
|
249
|
+
|
284
250
|
def assert_helpers_include(*helpers)
|
285
251
|
helpers.each do |helper|
|
286
|
-
['
|
287
|
-
[@controller, @view].each { |obj| assert_respond_to obj, "#{helper}#{suffix}".to_sym }
|
252
|
+
['url', 'path'].each do |suffix|
|
253
|
+
[@controller, @view].each { |obj| assert_respond_to obj, "#{helper}_#{suffix}".to_sym }
|
288
254
|
end
|
289
255
|
end
|
290
256
|
end
|
291
|
-
|
257
|
+
|
292
258
|
def assert_unrecognized_route(route_path, options)
|
293
259
|
assert_raise ActionController::RoutingError do
|
294
260
|
assert_routing route_path, options
|
295
261
|
end
|
296
262
|
end
|
297
263
|
|
298
|
-
def config_default_locale_settings(locale, with_prefix)
|
299
|
-
I18n.default_locale = locale
|
300
|
-
ActionController::Routing::Translator.prefix_on_default_locale = with_prefix
|
301
|
-
end
|
302
|
-
|
303
264
|
class StubbedI18nBackend
|
304
|
-
|
305
|
-
|
306
|
-
@@translations = {
|
307
|
-
'es' => { 'people' => 'gente'},
|
265
|
+
|
266
|
+
|
267
|
+
@@translations = {
|
268
|
+
'es' => { 'people' => 'gente'},
|
308
269
|
'fr' => {} # empty on purpose to test behaviour on incompleteness scenarios
|
309
270
|
}
|
310
|
-
|
271
|
+
|
311
272
|
def self.translate(locale, key, options)
|
312
273
|
@@translations[locale.to_s][key] || options[:default]
|
313
|
-
rescue
|
274
|
+
rescue
|
314
275
|
options[:default]
|
315
276
|
end
|
316
277
|
|
317
278
|
def self.available_locales
|
318
279
|
@@translations.keys
|
319
280
|
end
|
320
|
-
|
281
|
+
|
321
282
|
end
|
322
|
-
|
283
|
+
|
323
284
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: translate_routes_rails_2_3
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 1
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
|
+
- 3
|
7
8
|
- 0
|
8
|
-
-
|
9
|
-
|
10
|
-
version: 0.0.2
|
9
|
+
- 3
|
10
|
+
version: 3.0.3
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Raul Murciano
|
@@ -26,13 +26,11 @@ executables: []
|
|
26
26
|
extensions: []
|
27
27
|
|
28
28
|
extra_rdoc_files:
|
29
|
-
- ChangeLog
|
30
29
|
- README.markdown
|
31
30
|
files:
|
31
|
+
- lib/route_translator.rb
|
32
32
|
- lib/translate_routes.rb
|
33
|
-
- lib/translate_routes_i18n_available_locales.rb
|
34
33
|
- lib/translate_routes_test_helper.rb
|
35
|
-
- ChangeLog
|
36
34
|
- README.markdown
|
37
35
|
- test/translate_routes_test.rb
|
38
36
|
has_rdoc: true
|
@@ -68,6 +66,6 @@ rubyforge_project:
|
|
68
66
|
rubygems_version: 1.4.2
|
69
67
|
signing_key:
|
70
68
|
specification_version: 3
|
71
|
-
summary: Translate your Rails routes in a simple manner
|
69
|
+
summary: Translate your Rails routes in a simple manner
|
72
70
|
test_files:
|
73
71
|
- test/translate_routes_test.rb
|
data/ChangeLog
DELETED
@@ -1,22 +0,0 @@
|
|
1
|
-
-- 0.98
|
2
|
-
Accepted patch from hoelmer: Updated rake task to use I18n yaml format.
|
3
|
-
-- 0.97
|
4
|
-
Accepted patch from Aitor Garay-Romero: root routes with prefix now doesn't set the locale parameter.
|
5
|
-
|
6
|
-
-- rails2.2 branch -> master
|
7
|
-
|
8
|
-
-- branch rails2.2 v0.9 (Oct 27th 2008)
|
9
|
-
* Developed after Rails2.2rc1 release, with i18n support. Beta, not backward compatible with Rails < 2.2
|
10
|
-
|
11
|
-
-- 0.96.1 (Aug 5th 2008)
|
12
|
-
* Fixed by Mathieu Fosse: helpers didn't worked as expected when locale_param_key is undefined
|
13
|
-
|
14
|
-
-- 0.96 (Jun 10th 2008)
|
15
|
-
* Added update_yaml task, suggested by Francesc Esplugas
|
16
|
-
|
17
|
-
-- 0.95 (Jan 21st 2008)
|
18
|
-
* Still beta version
|
19
|
-
* Added yaml files support for dictionaries
|
20
|
-
|
21
|
-
-- 0.9 (Dec 27th 2007)
|
22
|
-
* Beta version
|
@@ -1,23 +0,0 @@
|
|
1
|
-
# monkeypatch I18n to get the available locales
|
2
|
-
# (not strictly needed to use translate_routes, but recommended anyway)
|
3
|
-
module I18n
|
4
|
-
class << self
|
5
|
-
def available_locales
|
6
|
-
backend.available_locales
|
7
|
-
end
|
8
|
-
end
|
9
|
-
|
10
|
-
module Backend
|
11
|
-
class Simple
|
12
|
-
def available_locales
|
13
|
-
init_translations unless initialized?
|
14
|
-
translations.keys
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
# load translation files from RAILS_ROOT/locales
|
21
|
-
[:rb, :yml].each do |format|
|
22
|
-
I18n.load_path = Dir[File.join(RAILS_ROOT, 'locales', '*.{rb,yml}') ]
|
23
|
-
end
|