fishman-i18n_routing 0.4.9
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/CHANGELOG.rdoc +99 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +81 -0
- data/MIT-LICENSE +20 -0
- data/README.rdoc +32 -0
- data/Rakefile +28 -0
- data/init.rb +2 -0
- data/lib/i18n_routing.rb +8 -0
- data/lib/i18n_routing_common.rb +52 -0
- data/lib/i18n_routing_rails2.rb +237 -0
- data/lib/i18n_routing_rails3.rb +392 -0
- data/lib/i18n_routing_rails3.rb.orig +388 -0
- data/spec/i18n_routing/i18n_spec.rb +397 -0
- data/spec/locales/en.yml +15 -0
- data/spec/locales/fr.yml +36 -0
- data/spec/locales/pt-br.yml +9 -0
- data/spec/spec_helper.rb +44 -0
- metadata +82 -0
@@ -0,0 +1,397 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe :localized_routes do
|
4
|
+
|
5
|
+
$r = nil # Global routes in order to speed up testing
|
6
|
+
|
7
|
+
before(:all) do
|
8
|
+
|
9
|
+
if !$r
|
10
|
+
if !rails3?
|
11
|
+
ActionController::Routing::Routes.clear!
|
12
|
+
ActionController::Routing::Routes.draw do |map|
|
13
|
+
map.not_about 'not_about', :controller => 'not_about'
|
14
|
+
map.resources :not_users
|
15
|
+
map.resource :not_contact
|
16
|
+
|
17
|
+
map.localized(I18n.available_locales, :verbose => false) do
|
18
|
+
map.about 'about', :controller => 'about', :action => :show
|
19
|
+
map.welcome 'welcome/to/our/page', :controller => :welcome, :action => :index
|
20
|
+
map.empty 'empty', :controller => 'empty', :action => :show
|
21
|
+
|
22
|
+
map.resources :users, :member => {:level => :get, :one => :get, :two => :get}, :collection => {:groups => :get}
|
23
|
+
map.resource :contact
|
24
|
+
|
25
|
+
map.resources :authors do |m|
|
26
|
+
m.resources :books
|
27
|
+
end
|
28
|
+
|
29
|
+
map.resources :empty_resources
|
30
|
+
|
31
|
+
map.resource :foo do |m|
|
32
|
+
m.resources :bars
|
33
|
+
m.resource :foofoo do |mm|
|
34
|
+
mm.resources :bars
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
map.resources :universes do |m|
|
39
|
+
m.resources :galaxies do |mm|
|
40
|
+
mm.resources :planets do |mmm|
|
41
|
+
mmm.resources :countries
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
map.with_options :path_prefix => ':locale' do |l|
|
47
|
+
l.localized_root '/', :controller => "about", :action => "show"
|
48
|
+
l.about_with_locale 'about', :controller => "about", :action => "show"
|
49
|
+
l.about_with_locale_with_sep 'about', :controller => "about", :action => "show"
|
50
|
+
l.resources :empty__resources
|
51
|
+
end
|
52
|
+
|
53
|
+
map.resources :drones, :path_prefix => 'doubledrones/unimatrix/zero'
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
$r = ActionController::Routing::Routes
|
58
|
+
|
59
|
+
class UrlTester
|
60
|
+
include ActionController::UrlWriter
|
61
|
+
end
|
62
|
+
|
63
|
+
else
|
64
|
+
|
65
|
+
$r = ActionDispatch::Routing::RouteSet.new
|
66
|
+
$r.draw do
|
67
|
+
match 'not_about' => "not_about#show", :as => :not_about
|
68
|
+
resources :not_users
|
69
|
+
resources :empty_resources
|
70
|
+
resource :not_contact
|
71
|
+
|
72
|
+
localized(I18n.available_locales, :verbose => true) do
|
73
|
+
match 'about' => "about#show", :as => :about
|
74
|
+
match 'welcome/to/our/page' => "welcome#index", :as => :welcome
|
75
|
+
match 'empty' => 'empty#show', :as => :empty
|
76
|
+
|
77
|
+
scope '/:locale', :constraints => { :locale => /[a-z]{2}/ } do ### this constraint fail on rails 3.0.4, so I had to hack a turn around
|
78
|
+
match '/' => "about#show", :as => :localized_root
|
79
|
+
match 'about' => "about#show", :as => :about_with_locale
|
80
|
+
match '/about' => "about#show", :as => :about_with_locale_with_sep
|
81
|
+
resources :empty__resources
|
82
|
+
end
|
83
|
+
|
84
|
+
resources :users do
|
85
|
+
member do
|
86
|
+
get :level
|
87
|
+
get :one, :two
|
88
|
+
end
|
89
|
+
get :groups, :on => :collection
|
90
|
+
end
|
91
|
+
resource :contact
|
92
|
+
|
93
|
+
resources :authors do
|
94
|
+
resources :books
|
95
|
+
end
|
96
|
+
|
97
|
+
resource :foo do
|
98
|
+
resources :bars
|
99
|
+
resource :foofoo do
|
100
|
+
resources :bars
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
resources :universes do
|
105
|
+
resources :galaxies do
|
106
|
+
resources :planets do
|
107
|
+
scope do
|
108
|
+
resources :countries
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
class UrlTester; end
|
118
|
+
UrlTester.send :include, $r.url_helpers
|
119
|
+
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
end
|
124
|
+
|
125
|
+
let(:nested_routes) { $r.named_routes.instance_eval { routes } }
|
126
|
+
let(:routes) { UrlTester.new }
|
127
|
+
|
128
|
+
def url_for(opts)
|
129
|
+
$r.generate_extras(opts).first
|
130
|
+
end
|
131
|
+
|
132
|
+
context "do not break existing behavior" do
|
133
|
+
|
134
|
+
it "of named_routes" do
|
135
|
+
routes.send(:not_about_path).should == "/not_about"
|
136
|
+
end
|
137
|
+
|
138
|
+
it "of a singular resource" do
|
139
|
+
routes.send(:not_contact_path).should == "/not_contact"
|
140
|
+
end
|
141
|
+
|
142
|
+
it "of resources" do
|
143
|
+
routes.send(:not_users_path).should == "/not_users"
|
144
|
+
end
|
145
|
+
|
146
|
+
end
|
147
|
+
|
148
|
+
context "for default routes" do
|
149
|
+
|
150
|
+
before do
|
151
|
+
I18n.locale = :de # Not localized
|
152
|
+
end
|
153
|
+
|
154
|
+
it "named_route uses default values" do
|
155
|
+
routes.send(:about_path).should == "/about"
|
156
|
+
routes.send(:welcome_path).should == '/welcome/to/our/page'
|
157
|
+
end
|
158
|
+
|
159
|
+
it "resource generates routes using default values" do
|
160
|
+
routes.send(:contact_path).should == "/contact"
|
161
|
+
end
|
162
|
+
|
163
|
+
it "resources generates routes using default values" do
|
164
|
+
routes.send(:users_path).should == "/users"
|
165
|
+
end
|
166
|
+
|
167
|
+
it "url_for generates route using default values" do
|
168
|
+
url_for(:controller => :users).should == "/users"
|
169
|
+
end
|
170
|
+
|
171
|
+
it "nested resources generate routes using default values" do
|
172
|
+
routes.send(:author_books_path, 1).should == "/authors/1/books"
|
173
|
+
end
|
174
|
+
|
175
|
+
it "deep nested resources generate routes using default values" do
|
176
|
+
routes.send(:universes_path).should == "/universes"
|
177
|
+
routes.send(:universe_galaxies_path, 1).should == "/universes/1/galaxies"
|
178
|
+
routes.send(:universe_galaxy_planets_path, 1, 1).should == "/universes/1/galaxies/1/planets"
|
179
|
+
end
|
180
|
+
|
181
|
+
it "single resource should have by default the pluralized controller" do
|
182
|
+
nested_routes[:foo].defaults[:controller].should == 'foos'
|
183
|
+
end
|
184
|
+
|
185
|
+
it "scope with parameters should be respected" do
|
186
|
+
routes.send(:localized_root_path, I18n.locale).should == "/#{I18n.locale}"
|
187
|
+
end
|
188
|
+
|
189
|
+
it "scope with parameters should be respected when filled" do
|
190
|
+
routes.send(:about_with_locale_path, I18n.locale).should == "/#{I18n.locale}/about"
|
191
|
+
routes.send(:about_with_locale_with_sep_path, I18n.locale).should == "/#{I18n.locale}/about"
|
192
|
+
end
|
193
|
+
|
194
|
+
end
|
195
|
+
|
196
|
+
context "" do
|
197
|
+
|
198
|
+
before do
|
199
|
+
I18n.locale = :fr
|
200
|
+
end
|
201
|
+
|
202
|
+
it "scope with parameters should be respected" do
|
203
|
+
routes.send(:localized_root_path, I18n.locale).should == "/#{I18n.locale}"
|
204
|
+
end
|
205
|
+
|
206
|
+
it "scope with parameters should be respected when filled" do
|
207
|
+
routes.send(:about_with_locale_path, I18n.locale).should == "/#{I18n.locale}/#{I18n.t :about, :scope => :named_routes_path}"
|
208
|
+
routes.send(:about_with_locale_with_sep_path, I18n.locale).should == "/#{I18n.locale}/#{I18n.t :about, :scope => :named_routes_path}"
|
209
|
+
end
|
210
|
+
|
211
|
+
it "named_route generates route using localized values" do
|
212
|
+
routes.send(:about_path).should == "/#{I18n.t :about, :scope => :named_routes_path}"
|
213
|
+
end
|
214
|
+
|
215
|
+
it "named_route generated route from actual route name" do
|
216
|
+
I18n.locale = :en
|
217
|
+
routes.send(:welcome_path).should == "/#{I18n.t :welcome, :scope => :named_routes}"
|
218
|
+
I18n.locale = :fr
|
219
|
+
end
|
220
|
+
|
221
|
+
it "named_route generates route from route path when route name not available" do
|
222
|
+
routes.send(:welcome_path).should == "/#{I18n.t 'welcome/to/our/page', :scope => :named_routes_path}"
|
223
|
+
end
|
224
|
+
|
225
|
+
it "doesn't translate empty route" do
|
226
|
+
routes.send(:empty_path).should_not == "/#{I18n.t 'empty', :scope => :named_routes_path}"
|
227
|
+
routes.send(:empty_path).should == "/empty"
|
228
|
+
routes.send(:empty_resources_path).should_not == "/#{I18n.t 'empty', :scope => :named_routes_path}"
|
229
|
+
routes.send(:empty_resources_path).should == "/empty_resources"
|
230
|
+
nested_routes.keys.include?(:fr_empty__resources).should == false # Because translation is empty
|
231
|
+
nested_routes.keys.include?('fr_empty__resources').should == false # Because translation is empty
|
232
|
+
end
|
233
|
+
|
234
|
+
it "named_route generates route using localized values and I18n.locale as a string" do
|
235
|
+
o = I18n.locale
|
236
|
+
I18n.locale = "fr"
|
237
|
+
routes.send(:about_path).should == "/#{I18n.t :about, :scope => :named_routes_path}"
|
238
|
+
I18n.locale = o
|
239
|
+
end
|
240
|
+
|
241
|
+
it "resource generates routes using localized values" do
|
242
|
+
routes.send(:contact_path).should == "/#{I18n.t :contact, :scope => :resource}"
|
243
|
+
end
|
244
|
+
|
245
|
+
it "resources generates routes using localized values" do
|
246
|
+
routes.send(:users_path).should == "/#{I18n.t :as, :scope => :'routes.users'}"
|
247
|
+
end
|
248
|
+
|
249
|
+
it "url_for generates routes using localized values" do
|
250
|
+
url_for(:controller => :users).should == "/#{I18n.t :as, :scope => :'routes.users'}"
|
251
|
+
url_for(:controller => :about, :action => :show).should == "/#{I18n.t :about, :scope => :named_routes_path}"
|
252
|
+
end
|
253
|
+
|
254
|
+
if !rails3?
|
255
|
+
it "url_for generates routes for drones with path prefix" do
|
256
|
+
url_for(:controller => :drones).should == "#{I18n.t :path_prefix, :scope => :'routes.drones'}/#{I18n.t :as, :scope => :'routes.drones'}"
|
257
|
+
end
|
258
|
+
end
|
259
|
+
|
260
|
+
it "nested resources generate routes using localized values" do
|
261
|
+
routes.send(:author_books_path, 1).should == "/#{I18n.t :authors, :scope => :resources}/1/#{I18n.t :books, :scope => :resources}"
|
262
|
+
end
|
263
|
+
|
264
|
+
it "deep nested resources generate routes using localized values and translate routes even translated name is the same" do
|
265
|
+
routes.send(:universes_path).should == "/#{I18n.t :universes, :scope => :resources}"
|
266
|
+
routes.send(:universe_galaxies_path, 1).should == "/#{I18n.t :universes, :scope => :resources}/1/#{I18n.t :galaxies, :scope => :resources}"
|
267
|
+
routes.send(:universe_galaxy_planets_path, 1, 1).should == "/#{I18n.t :universes, :scope => :resources}/1/#{I18n.t :galaxies, :scope => :resources}/1/#{I18n.t :planets, :scope => :resources}"
|
268
|
+
routes.send(:universe_galaxy_planet_countries_path, 1, 1, 42).should == "/#{I18n.t :universes, :scope => :resources}/1/#{I18n.t :galaxies, :scope => :resources}/1/#{I18n.t :planets, :scope => :resources}/42/#{I18n.t :countries, :scope => :resources}"
|
269
|
+
end
|
270
|
+
|
271
|
+
context "with path_names" do
|
272
|
+
|
273
|
+
it "default translated path names" do
|
274
|
+
routes.send(:new_universe_path).should == "/#{I18n.t :universes, :scope => :resources}/#{I18n.t :new, :scope => :path_names}"
|
275
|
+
routes.send(:edit_universe_path, 42).should == "/#{I18n.t :universes, :scope => :resources}/42/#{I18n.t :edit, :scope => :path_names}"
|
276
|
+
end
|
277
|
+
|
278
|
+
it "custom translated path names" do
|
279
|
+
routes.send(:new_user_path).should == "/#{I18n.t :users, :scope => :resources}/#{I18n.t :new, :scope => :'routes.users.path_names'}"
|
280
|
+
routes.send(:edit_user_path, 42).should == "/#{I18n.t :users, :scope => :resources}/42/#{I18n.t :edit, :scope => :'routes.users.path_names'}"
|
281
|
+
end
|
282
|
+
|
283
|
+
end
|
284
|
+
|
285
|
+
context "with member and collection" do
|
286
|
+
|
287
|
+
it "custom member" do
|
288
|
+
I18n.locale = :en
|
289
|
+
routes.send(:level_user_path, 42).should == "/#{I18n.t :users, :scope => :resources}/42/level"
|
290
|
+
I18n.locale = :fr
|
291
|
+
routes.send(:level_user_path, 42).should == "/#{I18n.t :users, :scope => :resources}/42/#{I18n.t :level, :scope => :'routes.users.path_names'}"
|
292
|
+
routes.send(:one_user_path, 42).should == "/#{I18n.t :users, :scope => :resources}/42/#{I18n.t :one, :scope => :'routes.users.path_names'}"
|
293
|
+
routes.send(:two_user_path, 42).should == "/#{I18n.t :users, :scope => :resources}/42/#{I18n.t :two, :scope => :'routes.users.path_names'}"
|
294
|
+
end
|
295
|
+
|
296
|
+
it "custom collection" do
|
297
|
+
I18n.locale = :en
|
298
|
+
routes.send(:groups_users_path).should == "/#{I18n.t :users, :scope => :resources}/groups"
|
299
|
+
I18n.locale = :fr
|
300
|
+
routes.send(:groups_users_path).should == "/#{I18n.t :users, :scope => :resources}/#{I18n.t :groups, :scope => :'routes.users.path_names'}"
|
301
|
+
end
|
302
|
+
|
303
|
+
end
|
304
|
+
|
305
|
+
context "when nested" do
|
306
|
+
|
307
|
+
it "named routes should not be nil" do
|
308
|
+
nested_routes[:author_fr_books].should_not be_nil
|
309
|
+
end
|
310
|
+
|
311
|
+
context "in Rails #{Rails.version}" do
|
312
|
+
it "include the correct significant keys" do
|
313
|
+
v = !rails3? ? :significant_keys : :segment_keys
|
314
|
+
nested_routes[:author_books].send(v).should include(:author_id)
|
315
|
+
nested_routes[:author_fr_books].send(v).should include(:author_id)
|
316
|
+
end
|
317
|
+
end
|
318
|
+
|
319
|
+
end
|
320
|
+
|
321
|
+
context "when nested inside a singleton resource" do
|
322
|
+
|
323
|
+
it "named routes should have locale placed at correct position" do
|
324
|
+
nested_routes[:fr_foo_fr_bars].should be_nil
|
325
|
+
nested_routes[:foo_fr_bars].should_not be_nil
|
326
|
+
end
|
327
|
+
|
328
|
+
it "routes for the singleton resource alone should be translated correctly" do
|
329
|
+
routes.send(:foo_path).should == "/#{I18n.t :foo, :scope => :resource}"
|
330
|
+
end
|
331
|
+
|
332
|
+
it "routes should be translated correctly" do
|
333
|
+
routes.send(:foo_bars_path).should == "/#{I18n.t :foo, :scope => :resource}/#{I18n.t :bars, :scope => :resources}"
|
334
|
+
end
|
335
|
+
|
336
|
+
it "routes should be translated correctly also with deep nested singleton resource" do
|
337
|
+
routes.send(:foo_foofoo_bars_path).should == "/#{I18n.t :foo, :scope => :resource}/#{I18n.t :foofoo, :scope => :resource}/#{I18n.t :bars, :scope => :resources}"
|
338
|
+
end
|
339
|
+
|
340
|
+
end
|
341
|
+
|
342
|
+
context "when deeply nested" do
|
343
|
+
|
344
|
+
it "named routes should not be nil" do
|
345
|
+
nested_routes[:universe_galaxy_fr_planet].should_not be_nil
|
346
|
+
end
|
347
|
+
|
348
|
+
context "in Rails #{Rails.version}" do
|
349
|
+
it "include the correct significant keys" do
|
350
|
+
v = !rails3? ? :significant_keys : :segment_keys
|
351
|
+
nested_routes[:universe_galaxy_planet].send(v).should include(:universe_id)
|
352
|
+
nested_routes[:universe_galaxy_fr_planet].send(v).should include(:universe_id)
|
353
|
+
nested_routes[:universe_galaxy_planet].send(v).should include(:galaxy_id)
|
354
|
+
nested_routes[:universe_galaxy_fr_planet].send(v).should include(:galaxy_id)
|
355
|
+
end
|
356
|
+
end
|
357
|
+
end
|
358
|
+
|
359
|
+
it "nested resources do not deep translate with multi helpers" do
|
360
|
+
nested_routes.keys.should_not include(:fr_author_books) # Do not want fr_author_books
|
361
|
+
end
|
362
|
+
|
363
|
+
end
|
364
|
+
|
365
|
+
context 'locale with a dash (pt-br)' do
|
366
|
+
|
367
|
+
before do
|
368
|
+
I18n.locale = 'pt-BR'
|
369
|
+
end
|
370
|
+
|
371
|
+
it 'users resources' do
|
372
|
+
routes.send(:users_path).should == "/#{I18n.t :users, :scope => :'resources'}"
|
373
|
+
end
|
374
|
+
|
375
|
+
it "routes for the singleton resource alone should be translated correctly" do
|
376
|
+
routes.send(:foo_path).should == "/#{I18n.t :foo, :scope => :resource}"
|
377
|
+
end
|
378
|
+
|
379
|
+
it "named_route generates route using localized values" do
|
380
|
+
routes.send(:about_path).should == "/#{I18n.t :about, :scope => :named_routes_path}"
|
381
|
+
end
|
382
|
+
|
383
|
+
it "custom translated path names" do
|
384
|
+
routes.send(:new_user_path).should == "/#{I18n.t :users, :scope => :resources}/#{I18n.t :new, :scope => :'path_names'}"
|
385
|
+
end
|
386
|
+
|
387
|
+
end
|
388
|
+
|
389
|
+
# context "just output" do
|
390
|
+
# it "output all routes properly" do
|
391
|
+
# nested_routes.keys.collect(&:to_s).sort.each do |k|
|
392
|
+
# puts("%50s: %.80s" % [k, (nested_routes[k.to_sym].path rescue nested_routes[k.to_sym].to_s)])
|
393
|
+
# end
|
394
|
+
# end
|
395
|
+
# end
|
396
|
+
|
397
|
+
end
|
data/spec/locales/en.yml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
en:
|
2
|
+
resources:
|
3
|
+
users: members
|
4
|
+
authors: 'authors-en'
|
5
|
+
galaxies: 'galaxies-en'
|
6
|
+
planets: 'planets-en'
|
7
|
+
universes: 'universes-en'
|
8
|
+
bars: bars_en
|
9
|
+
resource:
|
10
|
+
foo: foo_en
|
11
|
+
contact: 'contact-us'
|
12
|
+
named_routes_path:
|
13
|
+
about: 'about-our-company'
|
14
|
+
named_routes:
|
15
|
+
welcome: 'welcome-to-our-page'
|
data/spec/locales/fr.yml
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
fr:
|
2
|
+
routes:
|
3
|
+
users:
|
4
|
+
as: utilisateurs
|
5
|
+
path_names:
|
6
|
+
level: 'niveau'
|
7
|
+
groups: 'groupe'
|
8
|
+
new: 'nouvel_utilisateur'
|
9
|
+
edit: 'edition_utilisateur'
|
10
|
+
one: 'un'
|
11
|
+
two: 'deux'
|
12
|
+
drones:
|
13
|
+
as: senord
|
14
|
+
path_prefix: '/senordelbuod/xirtaminu/orez'
|
15
|
+
resources:
|
16
|
+
users: utilisateurs
|
17
|
+
authors: 'auteurs'
|
18
|
+
books: 'livres'
|
19
|
+
galaxies: 'galaxies'
|
20
|
+
planets: 'planetes'
|
21
|
+
universes: 'univers'
|
22
|
+
countries: 'pays'
|
23
|
+
bars: bars_fr
|
24
|
+
empty_resources: ''
|
25
|
+
empty__resources: ''
|
26
|
+
resource:
|
27
|
+
foo: foo_fr
|
28
|
+
foofoo: froufrou
|
29
|
+
contact: 'contactez-nous'
|
30
|
+
named_routes_path:
|
31
|
+
about: 'a-propos'
|
32
|
+
'welcome/to/our/page': 'bienvenue/sur/notre/site' # no idea about french translation ;-) --R
|
33
|
+
empty: ''
|
34
|
+
path_names:
|
35
|
+
new: 'nouveau'
|
36
|
+
edit: 'edition'
|