translate_routes_rails_2_3 0.0.2 → 3.0.3
Sign up to get free protection for your applications and to get access to all the features.
- 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
|