route_translator 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.travis.yml +7 -0
- data/Gemfile +5 -0
- data/LICENSE +20 -0
- data/README.md +128 -0
- data/Rakefile +22 -0
- data/gemfiles/Gemfile.rails-3.0.x +5 -0
- data/gemfiles/Gemfile.rails-3.1.x +5 -0
- data/lib/route_translator.rb +57 -0
- data/lib/route_translator/route_set.rb +36 -0
- data/lib/route_translator/route_set/dictionary_management.rb +76 -0
- data/lib/route_translator/route_set/helpers.rb +29 -0
- data/lib/route_translator/route_set/translator.rb +140 -0
- data/lib/route_translator/version.rb +3 -0
- data/lib/tasks/route_translator.rake +35 -0
- data/route_translator.gemspec +21 -0
- data/test/locales/routes.yml +10 -0
- data/test/route_translator_test.rb +328 -0
- data/test/test_helper.rb +49 -0
- metadata +83 -0
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2007 Raul Murciano [http://raul.murciano.net], Domestika INTERNET S.L. [http://domestika.org], 2012 Enric Lluelles [http://enric.lluell.es]
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,128 @@
|
|
1
|
+
RouteTranslator
|
2
|
+
===============
|
3
|
+
|
4
|
+
[](http://travis-ci.org/enriclluelles/route_translator)
|
5
|
+
|
6
|
+
RouteTranslator is a gem to allow you to manage the translations of your
|
7
|
+
app routes with a simple dictionary format
|
8
|
+
|
9
|
+
It started as a fork of the awesome [translate_routes](https://github.com/raul/translate_routes) plugin by [Raúl Murciano](https://github.com/raul) and then I made changes as I needed until it became the actual code
|
10
|
+
|
11
|
+
Right now it works with all the different flavous of rails3 (3.0, 3.1, 3.2) but I'm planning to make it compatible with rails 2.3 too. I'll see how it goes
|
12
|
+
|
13
|
+
|
14
|
+
Quick Start
|
15
|
+
-----------
|
16
|
+
|
17
|
+
1. If you have this `routes.rb` file originally:
|
18
|
+
|
19
|
+
```ruby
|
20
|
+
MyApp::Application.routes.draw do
|
21
|
+
|
22
|
+
namespace :admin do
|
23
|
+
resources :cars
|
24
|
+
end
|
25
|
+
|
26
|
+
resources :cars
|
27
|
+
end
|
28
|
+
```
|
29
|
+
|
30
|
+
the output of `rake routes.rb` would be this:
|
31
|
+
|
32
|
+
```
|
33
|
+
admin_cars GET /admin/cars(.:format) admin/cars#index
|
34
|
+
POST /admin/cars(.:format) admin/cars#create
|
35
|
+
new_admin_car GET /admin/cars/new(.:format) admin/cars#new
|
36
|
+
edit_admin_car GET /admin/cars/:id/edit(.:format) admin/cars#edit
|
37
|
+
admin_car GET /admin/cars/:id(.:format) admin/cars#show
|
38
|
+
PUT /admin/cars/:id(.:format) admin/cars#update
|
39
|
+
DELETE /admin/cars/:id(.:format) admin/cars#destroy
|
40
|
+
cars GET /cars(.:format) cars#index
|
41
|
+
POST /cars(.:format) cars#create
|
42
|
+
new_car GET /cars/new(.:format) cars#new
|
43
|
+
edit_car GET /cars/:id/edit(.:format) cars#edit
|
44
|
+
car GET /cars/:id(.:format) cars#show
|
45
|
+
PUT /cars/:id(.:format) cars#update
|
46
|
+
DELETE /cars/:id(.:format) cars#destroy
|
47
|
+
```
|
48
|
+
|
49
|
+
2. Add the gem to your `Gemfile`:
|
50
|
+
|
51
|
+
```ruby
|
52
|
+
gem 'route_translator'
|
53
|
+
```
|
54
|
+
|
55
|
+
And execute `bundle install`
|
56
|
+
|
57
|
+
3. Wrap the groups of routes that you want to translate inside a
|
58
|
+
`localized` block:
|
59
|
+
|
60
|
+
```ruby
|
61
|
+
MyApp::Application.routes.draw do
|
62
|
+
|
63
|
+
namespace :admin do
|
64
|
+
resources :cars
|
65
|
+
end
|
66
|
+
|
67
|
+
localized do
|
68
|
+
resources :cars
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
MyApp::Application.routes.translate_from_file #you can pass the file path as a param here
|
73
|
+
#the deault is config/i18n-routes.yml
|
74
|
+
```
|
75
|
+
|
76
|
+
And add the translations to a YAML file, for example
|
77
|
+
`config/i18n-routes.yml`:
|
78
|
+
|
79
|
+
```yaml
|
80
|
+
es:
|
81
|
+
cars: coches
|
82
|
+
new: nuevo
|
83
|
+
fr:
|
84
|
+
cars: voitures
|
85
|
+
new: nouveau
|
86
|
+
```
|
87
|
+
|
88
|
+
4. Your routes are translated! Here's the output of your `rake routes` now:
|
89
|
+
|
90
|
+
```
|
91
|
+
admin_cars GET /admin/cars(.:format) admin/cars#index
|
92
|
+
POST /admin/cars(.:format) admin/cars#create
|
93
|
+
new_admin_car GET /admin/cars/new(.:format) admin/cars#new
|
94
|
+
edit_admin_car GET /admin/cars/:id/edit(.:format) admin/cars#edit
|
95
|
+
admin_car GET /admin/cars/:id(.:format) admin/cars#show
|
96
|
+
PUT /admin/cars/:id(.:format) admin/cars#update
|
97
|
+
DELETE /admin/cars/:id(.:format) admin/cars#destroy
|
98
|
+
cars_en GET /cars(.:format) cars#index {:locale=>"en"}
|
99
|
+
cars_es GET /es/coches(.:format) cars#index {:locale=>"es"}
|
100
|
+
cars_fr GET /fr/voitures(.:format) cars#index {:locale=>"fr"}
|
101
|
+
POST /cars(.:format) cars#create {:locale=>"en"}
|
102
|
+
POST /es/coches(.:format) cars#create {:locale=>"es"}
|
103
|
+
POST /fr/voitures(.:format) cars#create {:locale=>"fr"}
|
104
|
+
new_car_en GET /cars/new(.:format) cars#new {:locale=>"en"}
|
105
|
+
new_car_es GET /es/coches/nuevo(.:format) cars#new {:locale=>"es"}
|
106
|
+
new_car_fr GET /fr/voitures/nouveau(.:format) cars#new {:locale=>"fr"}
|
107
|
+
edit_car_en GET /cars/:id/edit(.:format) cars#edit {:locale=>"en"}
|
108
|
+
edit_car_es GET /es/coches/:id/edit(.:format) cars#edit {:locale=>"es"}
|
109
|
+
edit_car_fr GET /fr/voitures/:id/edit(.:format) cars#edit {:locale=>"fr"}
|
110
|
+
car_en GET /cars/:id(.:format) cars#show {:locale=>"en"}
|
111
|
+
car_es GET /es/coches/:id(.:format) cars#show {:locale=>"es"}
|
112
|
+
car_fr GET /fr/voitures/:id(.:format) cars#show {:locale=>"fr"}
|
113
|
+
PUT /cars/:id(.:format) cars#update {:locale=>"en"}
|
114
|
+
PUT /es/coches/:id(.:format) cars#update {:locale=>"es"}
|
115
|
+
PUT /fr/voitures/:id(.:format) cars#update {:locale=>"fr"}
|
116
|
+
DELETE /cars/:id(.:format) cars#destroy {:locale=>"en"}
|
117
|
+
DELETE /es/coches/:id(.:format) cars#destroy {:locale=>"es"}
|
118
|
+
DELETE /fr/voitures/:id(.:format) cars#destroy {:locale=>"fr"}
|
119
|
+
```
|
120
|
+
|
121
|
+
Note that the route inside a `localized` are translated
|
122
|
+
|
123
|
+
5. Include this filter in your `ApplicationController` if you want to set
|
124
|
+
the I18n.locale value from the value set in the route
|
125
|
+
|
126
|
+
```ruby
|
127
|
+
before_filter :set_locale_from_url
|
128
|
+
```
|
data/Rakefile
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'rake/testtask'
|
3
|
+
require 'rdoc/task'
|
4
|
+
|
5
|
+
desc 'Default: run tests.'
|
6
|
+
task :default => :test
|
7
|
+
|
8
|
+
desc 'Test the translate_routes plugin.'
|
9
|
+
Rake::TestTask.new(:test) do |t|
|
10
|
+
t.libs << 'lib'
|
11
|
+
t.pattern = 'test/**/*_test.rb'
|
12
|
+
t.verbose = true
|
13
|
+
end
|
14
|
+
|
15
|
+
desc 'Generate documentation for the translate_routes plugin.'
|
16
|
+
Rake::RDocTask.new(:rdoc) do |rdoc|
|
17
|
+
rdoc.rdoc_dir = 'rdoc'
|
18
|
+
rdoc.title = 'RouteTranslator'
|
19
|
+
rdoc.options << '--line-numbers' << '--inline-source'
|
20
|
+
rdoc.rdoc_files.include('README')
|
21
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
22
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'active_support'
|
2
|
+
require 'action_controller'
|
3
|
+
require 'action_mailer'
|
4
|
+
require 'action_dispatch'
|
5
|
+
require 'route_translator/route_set'
|
6
|
+
|
7
|
+
module RouteTranslator
|
8
|
+
|
9
|
+
TRANSLATABLE_SEGMENT = /^([-_a-zA-Z0-9]+)(\()?/.freeze
|
10
|
+
LOCALE_PARAM_KEY = :locale
|
11
|
+
ROUTE_HELPER_CONTAINER = [
|
12
|
+
ActionController::Base,
|
13
|
+
ActionView::Base,
|
14
|
+
ActionMailer::Base,
|
15
|
+
ActionDispatch::Routing::UrlFor
|
16
|
+
].freeze
|
17
|
+
|
18
|
+
def self.locale_suffix locale
|
19
|
+
locale.to_s.underscore
|
20
|
+
end
|
21
|
+
|
22
|
+
# Attributes
|
23
|
+
|
24
|
+
module Controller
|
25
|
+
def set_locale_from_url
|
26
|
+
I18n.locale = params[RouteTranslator::LOCALE_PARAM_KEY]
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
module Mapper
|
31
|
+
#yield the block and add all the routes created
|
32
|
+
#in it to the localized_routes array
|
33
|
+
def localized
|
34
|
+
routes_before = @set.routes.map(&:to_s)
|
35
|
+
yield
|
36
|
+
routes_after = @set.routes.map(&:to_s)
|
37
|
+
@set.localized_routes ||= []
|
38
|
+
@set.localized_routes.concat(routes_after - routes_before)
|
39
|
+
@set.localized_routes.uniq!
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
# Add locale_suffix to controllers, views and mailers
|
46
|
+
RouteTranslator::ROUTE_HELPER_CONTAINER.each do |klass|
|
47
|
+
klass.class_eval do
|
48
|
+
private
|
49
|
+
def locale_suffix locale
|
50
|
+
RouteTranslator.locale_suffix locale
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
ActionController::Base.send(:include, RouteTranslator::Controller)
|
56
|
+
ActionDispatch::Routing::Mapper.send(:include, RouteTranslator::Mapper)
|
57
|
+
ActionDispatch::Routing::RouteSet.send(:include, RouteTranslator::RouteSet)
|
@@ -0,0 +1,36 @@
|
|
1
|
+
%w(helpers translator dictionary_management).each do |f|
|
2
|
+
require File.expand_path(File.join(File.dirname(__FILE__), 'route_set', f))
|
3
|
+
end
|
4
|
+
|
5
|
+
|
6
|
+
module RouteTranslator
|
7
|
+
module RouteSet
|
8
|
+
include DictionaryManagement
|
9
|
+
include Translator
|
10
|
+
|
11
|
+
attr_accessor :dictionary, :localized_routes
|
12
|
+
|
13
|
+
#Use the i18n setting from the app
|
14
|
+
def translate_with_i18n(*wanted_locales)
|
15
|
+
init_i18n_dictionary(*wanted_locales)
|
16
|
+
translate
|
17
|
+
end
|
18
|
+
|
19
|
+
#Use yield the block passing and empty dictionary as a paramenter
|
20
|
+
def translate_with_dictionary(&block)
|
21
|
+
yield_dictionary &block
|
22
|
+
translate
|
23
|
+
end
|
24
|
+
|
25
|
+
#Use the translations from the specified file
|
26
|
+
def translate_from_file(file_path = nil)
|
27
|
+
file_path ||= defined?(Rails) && File.join(Rails.root, %w(config i18-routes.yml))
|
28
|
+
load_dictionary_from_file(file_path)
|
29
|
+
translate
|
30
|
+
end
|
31
|
+
|
32
|
+
include Helpers
|
33
|
+
include Translator
|
34
|
+
include DictionaryManagement
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
module RouteTranslator
|
2
|
+
module RouteSet
|
3
|
+
module DictionaryManagement
|
4
|
+
# Resets dictionary and yields the block wich can be used to manually fill the dictionary
|
5
|
+
# with translations e.g.
|
6
|
+
# route_translator = RouteTranslator.new
|
7
|
+
# route_translator.yield_dictionary do |dict|
|
8
|
+
# dict['en'] = { 'people' => 'people' }
|
9
|
+
# dict['de'] = { 'people' => 'personen' }
|
10
|
+
# end
|
11
|
+
def yield_dictionary &block
|
12
|
+
reset_dictionary
|
13
|
+
yield @dictionary
|
14
|
+
set_available_locales_from_dictionary
|
15
|
+
end
|
16
|
+
|
17
|
+
# Resets dictionary and loads translations from specified file
|
18
|
+
# config/locales/routes.yml:
|
19
|
+
# en:
|
20
|
+
# people: people
|
21
|
+
# de:
|
22
|
+
# people: personen
|
23
|
+
# routes.rb:
|
24
|
+
# ... your routes ...
|
25
|
+
# ActionDispatch::Routing::Translator.translate_from_file
|
26
|
+
# or, to specify a custom file
|
27
|
+
# ActionDispatch::Routing::Translator.translate_from_file 'config', 'locales', 'routes.yml'
|
28
|
+
def load_dictionary_from_file file_path
|
29
|
+
reset_dictionary
|
30
|
+
add_dictionary_from_file file_path
|
31
|
+
end
|
32
|
+
|
33
|
+
# Add translations from another file to the dictionary.
|
34
|
+
def add_dictionary_from_file file_path
|
35
|
+
yaml = YAML.load_file(file_path)
|
36
|
+
yaml.each_pair do |locale, translations|
|
37
|
+
merge_translations locale, translations
|
38
|
+
end
|
39
|
+
set_available_locales_from_dictionary
|
40
|
+
end
|
41
|
+
|
42
|
+
# Merge translations for a specified locale into the dictionary
|
43
|
+
def merge_translations locale, translations
|
44
|
+
locale = locale.to_s
|
45
|
+
if translations.blank?
|
46
|
+
@dictionary[locale] ||= {}
|
47
|
+
return
|
48
|
+
end
|
49
|
+
@dictionary[locale] = (@dictionary[locale] || {}).merge(translations)
|
50
|
+
end
|
51
|
+
|
52
|
+
# Init dictionary to use I18n to translate route parts. Creates
|
53
|
+
# a hash with a block for each locale to lookup keys in I18n dynamically.
|
54
|
+
def init_i18n_dictionary *wanted_locales
|
55
|
+
wanted_locales = available_locales if wanted_locales.blank?
|
56
|
+
reset_dictionary
|
57
|
+
wanted_locales.each do |locale|
|
58
|
+
@dictionary[locale] = Hash.new do |hsh, key|
|
59
|
+
hsh[key] = I18n.translate key, :locale => locale #DISCUSS: caching or no caching (store key and translation in dictionary?)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
@available_locales = @dictionary.keys.map &:to_s
|
63
|
+
end
|
64
|
+
|
65
|
+
private
|
66
|
+
def set_available_locales_from_dictionary
|
67
|
+
@available_locales = @dictionary.keys.map &:to_s
|
68
|
+
end
|
69
|
+
|
70
|
+
# Resets dictionary
|
71
|
+
def reset_dictionary
|
72
|
+
@dictionary = { default_locale => {}}
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module RouteTranslator
|
2
|
+
module RouteSet
|
3
|
+
module Helpers
|
4
|
+
def available_locales
|
5
|
+
@available_locales ||= I18n.available_locales.map(&:to_s)
|
6
|
+
end
|
7
|
+
|
8
|
+
def available_locales= locales
|
9
|
+
@available_locales = locales.map(&:to_s)
|
10
|
+
end
|
11
|
+
|
12
|
+
def default_locale
|
13
|
+
@default_locale ||= I18n.default_locale.to_s
|
14
|
+
end
|
15
|
+
|
16
|
+
def default_locale= locale
|
17
|
+
@default_locale = locale.to_s
|
18
|
+
end
|
19
|
+
|
20
|
+
def default_locale? locale
|
21
|
+
default_locale == locale.to_s
|
22
|
+
end
|
23
|
+
|
24
|
+
def locale_suffix locale
|
25
|
+
RouteTranslator.locale_suffix locale
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,140 @@
|
|
1
|
+
module RouteTranslator
|
2
|
+
module RouteSet
|
3
|
+
module Translator
|
4
|
+
# Translate a specific RouteSet, usually Rails.application.routes, but can
|
5
|
+
# be a RouteSet of a gem, plugin/engine etc.
|
6
|
+
def translate
|
7
|
+
Rails.logger.info "Translating routes (default locale: #{default_locale})" if defined?(Rails) && defined?(Rails.logger)
|
8
|
+
|
9
|
+
# save original routes and clear route set
|
10
|
+
original_routes = routes.dup
|
11
|
+
original_named_routes = named_routes.routes.dup # Hash {:name => :route}
|
12
|
+
|
13
|
+
routes_to_create = []
|
14
|
+
original_routes.each do |original_route|
|
15
|
+
if localized_routes && localized_routes.include?(original_route.to_s) then
|
16
|
+
translations_for(original_route).each do |translated_route_args|
|
17
|
+
routes_to_create << translated_route_args
|
18
|
+
end
|
19
|
+
else
|
20
|
+
route = untranslated_route original_route
|
21
|
+
routes_to_create << route
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
reset!
|
26
|
+
|
27
|
+
routes_to_create.each do |r|
|
28
|
+
add_route(*r)
|
29
|
+
end
|
30
|
+
|
31
|
+
|
32
|
+
Hash[original_named_routes.select{|k,v| localized_routes && localized_routes.include?(v.to_s)}].each_key do |route_name|
|
33
|
+
named_routes.helpers.concat add_untranslated_helpers_to_controllers_and_views(route_name)
|
34
|
+
end
|
35
|
+
|
36
|
+
finalize!
|
37
|
+
named_routes.install
|
38
|
+
end
|
39
|
+
|
40
|
+
# Add standard route helpers for default locale e.g.
|
41
|
+
# I18n.locale = :de
|
42
|
+
# people_path -> people_de_path
|
43
|
+
# I18n.locale = :fr
|
44
|
+
# people_path -> people_fr_path
|
45
|
+
def add_untranslated_helpers_to_controllers_and_views old_name
|
46
|
+
['path', 'url'].map do |suffix|
|
47
|
+
new_helper_name = "#{old_name}_#{suffix}"
|
48
|
+
|
49
|
+
ROUTE_HELPER_CONTAINER.each do |helper_container|
|
50
|
+
helper_container.send :define_method, new_helper_name do |*args|
|
51
|
+
if respond_to? "#{old_name}_#{locale_suffix(I18n.locale)}_#{suffix}"
|
52
|
+
send "#{old_name}_#{locale_suffix(I18n.locale)}_#{suffix}", *args
|
53
|
+
else
|
54
|
+
send "#{old_name}_#{locale_suffix(I18n.default_locale)}_#{suffix}", *args
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
new_helper_name.to_sym
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
# Generate translations for a single route for all available locales
|
64
|
+
def translations_for route
|
65
|
+
available_locales.map do |locale|
|
66
|
+
translate_route(route, locale.dup) #we duplicate the locale string to ensure it's not frozen
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
# Generate translation for a single route for one locale
|
71
|
+
def translate_route route, locale
|
72
|
+
path_regex = route.path.respond_to?(:spec) ? route.path.spec : route.path
|
73
|
+
|
74
|
+
conditions = route.conditions.dup.merge({
|
75
|
+
:path_info => translate_path(path_regex.dup.to_s, locale)
|
76
|
+
})
|
77
|
+
|
78
|
+
conditions[:request_method] = request_method_array(conditions[:request_method]) if conditions[:request_method]
|
79
|
+
|
80
|
+
requirements = route.requirements.dup.merge!(LOCALE_PARAM_KEY => locale)
|
81
|
+
defaults = route.defaults.dup.merge LOCALE_PARAM_KEY => locale
|
82
|
+
|
83
|
+
new_name = "#{route.name}_#{locale_suffix(locale)}" if route.name
|
84
|
+
|
85
|
+
[route.app, conditions, requirements, defaults, new_name]
|
86
|
+
end
|
87
|
+
|
88
|
+
def untranslated_route route
|
89
|
+
path_regex = route.path.respond_to?(:spec) ? route.path.spec : route.path
|
90
|
+
|
91
|
+
conditions = route.conditions.dup.merge({
|
92
|
+
:path_info => path_regex.to_s
|
93
|
+
})
|
94
|
+
|
95
|
+
conditions[:request_method] = request_method_array(conditions[:request_method]) if conditions[:request_method]
|
96
|
+
|
97
|
+
[route.app, conditions, route.requirements.dup, route.defaults.dup, route.name]
|
98
|
+
end
|
99
|
+
|
100
|
+
def request_method_array(reg)
|
101
|
+
reg.source.gsub(%r{\^|\$}, "").split("|")
|
102
|
+
end
|
103
|
+
|
104
|
+
# Translates a path and adds the locale prefix.
|
105
|
+
def translate_path(path, locale)
|
106
|
+
final_optional_segments = path.slice!(/(\(.+\))$/)
|
107
|
+
new_path = path.split("/").map{|seg| translate_path_segment(seg, locale)}.join('/')
|
108
|
+
new_path = "/#{locale.downcase}#{new_path}" unless default_locale?(locale)
|
109
|
+
new_path = "/" if new_path.blank?
|
110
|
+
"#{new_path}#{final_optional_segments}"
|
111
|
+
end
|
112
|
+
|
113
|
+
# Tries to translate a single path segment. If the path segment
|
114
|
+
# contains sth. like a optional format "people(.:format)", only
|
115
|
+
# "people" will be translated, if there is no translation, the path
|
116
|
+
# segment is blank or begins with a ":" (param key), the segment
|
117
|
+
# is returned untouched
|
118
|
+
def translate_path_segment segment, locale
|
119
|
+
return segment if segment.blank? or segment.starts_with?(":")
|
120
|
+
|
121
|
+
match = TRANSLATABLE_SEGMENT.match(segment)[1] rescue nil
|
122
|
+
|
123
|
+
(translate_string(match, locale) || segment)
|
124
|
+
end
|
125
|
+
|
126
|
+
def translate_string(str, locale)
|
127
|
+
@dictionary[locale.to_s][str.to_s]
|
128
|
+
end
|
129
|
+
|
130
|
+
private
|
131
|
+
|
132
|
+
def reset!
|
133
|
+
clear!
|
134
|
+
named_routes.module.instance_methods.each do |method|
|
135
|
+
named_routes.module.send(:remove_method, method)
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
namespace :translate_routes => :environment do
|
2
|
+
|
3
|
+
desc "Updates yaml translation files for the given languages"
|
4
|
+
task :update_yaml, :langs, :needs => :environment do |task, args|
|
5
|
+
segments = ActionController::Routing::Translator.original_static_segments
|
6
|
+
|
7
|
+
if args[:langs].is_a?(String)
|
8
|
+
langs = args[:langs] + ' ' + ActionController::Routing::Translator.default_locale
|
9
|
+
langs.split.uniq.each do |lang|
|
10
|
+
|
11
|
+
file_path = File.join(config_path, "routes_#{lang}.yml");
|
12
|
+
|
13
|
+
if File.exists?(file_path)
|
14
|
+
puts "Updating #{file_path}"
|
15
|
+
translations = YAML.load_file(file_path)
|
16
|
+
f = File.open(file_path,'w')
|
17
|
+
else
|
18
|
+
puts "Creating #{file_path}"
|
19
|
+
translations = {}
|
20
|
+
f = File.new(file_path, 'w')
|
21
|
+
end
|
22
|
+
|
23
|
+
f.write "#{lang}:\n"
|
24
|
+
segments.each do |s|
|
25
|
+
translation = translations[lang][s] rescue ''
|
26
|
+
f.write " #{s}: #{translation}\n"
|
27
|
+
end
|
28
|
+
f.close
|
29
|
+
end
|
30
|
+
|
31
|
+
else
|
32
|
+
puts 'Missing parameters, usage example: rake translate_routes:update_yaml["fr de es"]'
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require File.expand_path('../lib/route_translator/version', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |s|
|
5
|
+
s.name = "route_translator"
|
6
|
+
s.version = RouteTranslator::VERSION
|
7
|
+
|
8
|
+
s.authors = ["Raul Murciano", "Enric Lluelles"]
|
9
|
+
s.email = %q{enric@lluell.es}
|
10
|
+
|
11
|
+
s.homepage = %q{http://github.com/enriclluelles/route_translator}
|
12
|
+
|
13
|
+
s.description = %q{Translates the Rails routes of your application into the languages defined in your locale files}
|
14
|
+
s.summary = %q{Translate your Rails routes in a simple manner}
|
15
|
+
|
16
|
+
s.files = `git ls-files`.split($\) - %w(.gitignore test_runner)
|
17
|
+
s.test_files = `git ls-files test`.split($\)
|
18
|
+
s.require_paths = ["lib"]
|
19
|
+
|
20
|
+
s.add_runtime_dependency("mocha")
|
21
|
+
end
|
@@ -0,0 +1,328 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'mocha'
|
3
|
+
|
4
|
+
require 'route_translator'
|
5
|
+
|
6
|
+
require File.expand_path(File.join(File.dirname(__FILE__), 'test_helper'))
|
7
|
+
|
8
|
+
|
9
|
+
class PeopleController < ActionController::Base; end
|
10
|
+
class ProductsController < ActionController::Base; end
|
11
|
+
|
12
|
+
class TranslateRoutesTest < ActionController::TestCase
|
13
|
+
include ActionDispatch::Assertions::RoutingAssertions
|
14
|
+
include RouteTranslator::TestHelper
|
15
|
+
|
16
|
+
def config_default_locale_settings(locale)
|
17
|
+
I18n.default_locale = locale
|
18
|
+
end
|
19
|
+
|
20
|
+
def setup
|
21
|
+
@controller = ActionController::Base.new
|
22
|
+
@view = ActionView::Base.new
|
23
|
+
@routes = ActionDispatch::Routing::RouteSet.new
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_unnamed_root_route
|
27
|
+
@routes.draw do
|
28
|
+
localized do
|
29
|
+
root :to => 'people#index'
|
30
|
+
end
|
31
|
+
end
|
32
|
+
config_default_locale_settings 'en'
|
33
|
+
@routes.translate_with_dictionary{|t| t['en'] = {}; t['es'] = {'people' => 'gente'} }
|
34
|
+
|
35
|
+
assert_routing '/', :controller => 'people', :action => 'index', :locale => 'en'
|
36
|
+
assert_routing '/es', :controller => 'people', :action => 'index', :locale => 'es'
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_unnamed_root_route_without_prefix
|
40
|
+
@routes.draw do
|
41
|
+
localized do
|
42
|
+
root :to => 'people#index'
|
43
|
+
end
|
44
|
+
end
|
45
|
+
config_default_locale_settings 'es'
|
46
|
+
|
47
|
+
@routes.translate_from_file(File.expand_path('locales/routes.yml', File.dirname(__FILE__)))
|
48
|
+
|
49
|
+
assert_routing '/', :controller => 'people', :action => 'index', :locale => 'es'
|
50
|
+
assert_routing '/en', :controller => 'people', :action => 'index', :locale => 'en'
|
51
|
+
assert_unrecognized_route '/es', :controller => 'people', :action => 'index', :locale => 'es'
|
52
|
+
end
|
53
|
+
|
54
|
+
def test_unnamed_untranslated_route
|
55
|
+
@routes.draw do
|
56
|
+
localized do
|
57
|
+
match 'foo', :to => 'people#index'
|
58
|
+
end
|
59
|
+
end
|
60
|
+
config_default_locale_settings 'en'
|
61
|
+
@routes.translate_with_dictionary{|t| t['en'] = {}; t['es'] = {'people' => 'gente'} }
|
62
|
+
|
63
|
+
assert_routing '/es/foo', :controller => 'people', :action => 'index', :locale => 'es'
|
64
|
+
assert_routing '/foo', :controller => 'people', :action => 'index', :locale => 'en'
|
65
|
+
end
|
66
|
+
|
67
|
+
def test_unnamed_translated_route_on_default_locale
|
68
|
+
@routes.draw { match 'people', :to => 'people#index' }
|
69
|
+
@routes.draw do
|
70
|
+
localized do
|
71
|
+
match 'people', :to => 'people#index'
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
config_default_locale_settings 'es'
|
76
|
+
|
77
|
+
@routes.translate_with_dictionary{|t| t['en'] = {}; t['es'] = {'people' => 'gente'} }
|
78
|
+
|
79
|
+
assert_routing '/en/people', :controller => 'people', :action => 'index', :locale => 'en'
|
80
|
+
assert_routing '/gente', :controller => 'people', :action => 'index', :locale => 'es'
|
81
|
+
end
|
82
|
+
|
83
|
+
def test_unnamed_translated_route_on_non_default_locale
|
84
|
+
@routes.draw do
|
85
|
+
localized do
|
86
|
+
match 'people', :to => 'people#index'
|
87
|
+
end
|
88
|
+
end
|
89
|
+
config_default_locale_settings 'en'
|
90
|
+
@routes.translate_with_dictionary{|t| t['en'] = {}; t['es'] = {'people' => 'gente'} }
|
91
|
+
|
92
|
+
assert_routing '/es/gente', :controller => 'people', :action => 'index', :locale => 'es'
|
93
|
+
assert_routing '/people', :controller => 'people', :action => 'index', :locale => 'en'
|
94
|
+
end
|
95
|
+
|
96
|
+
def test_named_translated_route_with_prefix_must_have_locale_as_static_segment
|
97
|
+
@routes.draw do
|
98
|
+
localized do
|
99
|
+
match 'people', :to => 'people#index'
|
100
|
+
end
|
101
|
+
end
|
102
|
+
config_default_locale_settings 'en'
|
103
|
+
@routes.translate_with_dictionary{|t| t['en'] = {}; t['es'] = {'people' => 'gente'} }
|
104
|
+
|
105
|
+
# we check the string representation of the route,
|
106
|
+
# if it stores locale as a dynamic segment it would be represented as: "/:locale/gente"
|
107
|
+
assert_equal "/es/gente(.:format)", path_string(named_route('people_es'))
|
108
|
+
end
|
109
|
+
|
110
|
+
def test_named_empty_route_without_prefix
|
111
|
+
@routes.draw do
|
112
|
+
localized do
|
113
|
+
root :to => 'people#index', :as => 'people'
|
114
|
+
end
|
115
|
+
end
|
116
|
+
config_default_locale_settings 'es'
|
117
|
+
@routes.translate_with_dictionary{|t| t['es'] = {}; t['en'] = {'people' => 'gente'}; }
|
118
|
+
|
119
|
+
assert_routing '/en', :controller => 'people', :action => 'index', :locale => 'en'
|
120
|
+
assert_routing '/', :controller => 'people', :action => 'index', :locale => 'es'
|
121
|
+
assert_routing '', :controller => 'people', :action => 'index', :locale => 'es'
|
122
|
+
end
|
123
|
+
|
124
|
+
def test_named_root_route_without_prefix
|
125
|
+
@routes.draw do
|
126
|
+
localized do
|
127
|
+
root :to => 'people#index'
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
config_default_locale_settings 'es'
|
132
|
+
|
133
|
+
@routes.translate_from_file(File.expand_path('locales/routes.yml', File.dirname(__FILE__)))
|
134
|
+
|
135
|
+
assert_routing '/', :controller => 'people', :action => 'index', :locale => 'es'
|
136
|
+
assert_routing '/en', :controller => 'people', :action => 'index', :locale => 'en'
|
137
|
+
assert_unrecognized_route '/es', :controller => 'people', :action => 'index', :locale => 'es'
|
138
|
+
end
|
139
|
+
|
140
|
+
def test_named_untranslated_route_without_prefix
|
141
|
+
@routes.draw do
|
142
|
+
localized do
|
143
|
+
match 'foo', :to => 'people#index', :as => 'people'
|
144
|
+
end
|
145
|
+
end
|
146
|
+
config_default_locale_settings 'es'
|
147
|
+
@routes.translate_with_dictionary{ |t| t['en'] = {}; t['es'] = {'people' => 'gente'} }
|
148
|
+
|
149
|
+
assert_routing '/en/foo', :controller => 'people', :action => 'index', :locale => 'en'
|
150
|
+
assert_routing '/foo', :controller => 'people', :action => 'index', :locale => 'es'
|
151
|
+
assert_helpers_include :people_en, :people_es, :people
|
152
|
+
end
|
153
|
+
|
154
|
+
def test_named_translated_route_on_default_locale_without_prefix
|
155
|
+
@routes.draw do
|
156
|
+
localized do
|
157
|
+
match 'people', :to => 'people#index', :as => 'people'
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
config_default_locale_settings 'es'
|
162
|
+
|
163
|
+
@routes.translate_with_dictionary{|t| t['en'] = {}; t['es'] = {'people' => 'gente'} }
|
164
|
+
|
165
|
+
assert_routing '/en/people', :controller => 'people', :action => 'index', :locale => 'en'
|
166
|
+
assert_routing 'gente', :controller => 'people', :action => 'index', :locale => 'es'
|
167
|
+
assert_helpers_include :people_en, :people_es, :people
|
168
|
+
end
|
169
|
+
|
170
|
+
def test_named_translated_route_on_non_default_locale_without_prefix
|
171
|
+
@routes.draw do
|
172
|
+
localized do
|
173
|
+
match 'people', :to => 'people#index', :as => 'people'
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
config_default_locale_settings 'en'
|
178
|
+
|
179
|
+
@routes.translate_with_dictionary{|t| t['en'] = {}; t['es'] = {'people' => 'gente'} }
|
180
|
+
|
181
|
+
assert_routing '/people', :controller => 'people', :action => 'index', :locale => 'en'
|
182
|
+
assert_routing '/es/gente', :controller => 'people', :action => 'index', :locale => 'es'
|
183
|
+
assert_helpers_include :people_en, :people_es, :people
|
184
|
+
end
|
185
|
+
|
186
|
+
def test_formatted_root_route
|
187
|
+
@routes.draw do
|
188
|
+
localized do
|
189
|
+
root :to => 'people#index', :as => 'root'
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
@routes.translate_with_dictionary{ |t| t['en'] = {}; t['es'] = {'people' => 'gente'} }
|
194
|
+
|
195
|
+
if formatted_root_route?
|
196
|
+
assert_equal '/(.:format)', path_string(named_route('root_en'))
|
197
|
+
assert_equal '/es(.:format)', path_string(named_route('root_es'))
|
198
|
+
else
|
199
|
+
assert_equal '/', path_string(named_route('root_en'))
|
200
|
+
assert_equal '/es', path_string(named_route('root_es'))
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
def test_routes_locale_prefixes_are_never_downcased
|
205
|
+
@routes.draw do
|
206
|
+
localized do
|
207
|
+
match 'people', :to => 'people#index', :as => 'people'
|
208
|
+
end
|
209
|
+
end
|
210
|
+
config_default_locale_settings 'en'
|
211
|
+
|
212
|
+
@routes.translate_with_dictionary{ |t| t['en'] = {}; t['ES'] = {'people' => 'Gente'} }
|
213
|
+
|
214
|
+
assert_routing '/es/Gente', :controller => 'people', :action => 'index', :locale => 'ES'
|
215
|
+
end
|
216
|
+
|
217
|
+
def test_languages_load_from_file
|
218
|
+
@routes.draw do
|
219
|
+
localized do
|
220
|
+
match 'people', :to => 'people#index', :as => 'people'
|
221
|
+
end
|
222
|
+
end
|
223
|
+
config_default_locale_settings 'en'
|
224
|
+
|
225
|
+
@routes.translate_from_file(File.expand_path('locales/routes.yml', File.dirname(__FILE__)))
|
226
|
+
|
227
|
+
assert_routing '/people', :controller => 'people', :action => 'index', :locale => 'en'
|
228
|
+
assert_routing '/es/gente', :controller => 'people', :action => 'index', :locale => 'es'
|
229
|
+
assert_helpers_include :people_en, :people_es, :people
|
230
|
+
end
|
231
|
+
|
232
|
+
def test_languages_load_from_file_without_dictionary_for_default_locale
|
233
|
+
@routes.draw do
|
234
|
+
localized do
|
235
|
+
match 'people', :to => 'people#index', :as => 'people'
|
236
|
+
end
|
237
|
+
end
|
238
|
+
config_default_locale_settings 'fr'
|
239
|
+
|
240
|
+
@routes.translate_from_file(File.expand_path('locales/routes.yml', File.dirname(__FILE__)))
|
241
|
+
|
242
|
+
assert_routing '/people', :controller => 'people', :action => 'index', :locale => 'fr'
|
243
|
+
assert_routing '/en/people', :controller => 'people', :action => 'index', :locale => 'en'
|
244
|
+
assert_routing '/es/gente', :controller => 'people', :action => 'index', :locale => 'es'
|
245
|
+
assert_helpers_include :people_fr, :people_en, :people_es, :people
|
246
|
+
end
|
247
|
+
|
248
|
+
def test_i18n_based_translations_setting_locales
|
249
|
+
@routes.draw do
|
250
|
+
localized do
|
251
|
+
match 'people', :to => 'people#index', :as => 'people'
|
252
|
+
end
|
253
|
+
end
|
254
|
+
config_default_locale_settings 'en'
|
255
|
+
|
256
|
+
I18n.backend = StubbedI18nBackend
|
257
|
+
|
258
|
+
@routes.translate_with_i18n('es')
|
259
|
+
|
260
|
+
assert_routing '/es/gente', :controller => 'people', :action => 'index', :locale => 'es'
|
261
|
+
assert_routing '/people', :controller => 'people', :action => 'index', :locale => 'en'
|
262
|
+
assert_helpers_include :people_en, :people_es, :people
|
263
|
+
end
|
264
|
+
|
265
|
+
def test_i18n_based_translations_taking_i18n_available_locales
|
266
|
+
@routes.draw do
|
267
|
+
localized do
|
268
|
+
match 'people', :to => 'people#index', :as => 'people'
|
269
|
+
end
|
270
|
+
end
|
271
|
+
config_default_locale_settings 'en'
|
272
|
+
I18n.stubs(:available_locales).at_least_once.returns StubbedI18nBackend.available_locales
|
273
|
+
I18n.backend = StubbedI18nBackend
|
274
|
+
|
275
|
+
@routes.translate_with_i18n
|
276
|
+
|
277
|
+
assert_routing '/fr/people', :controller => 'people', :action => 'index', :locale => 'fr'
|
278
|
+
assert_routing '/es/gente', :controller => 'people', :action => 'index', :locale => 'es'
|
279
|
+
assert_routing '/people', :controller => 'people', :action => 'index', :locale => 'en'
|
280
|
+
assert_helpers_include :people_fr, :people_en, :people_es, :people
|
281
|
+
end
|
282
|
+
|
283
|
+
def test_2_localized_blocks
|
284
|
+
@routes.draw do
|
285
|
+
localized do
|
286
|
+
match 'people', :to => 'people#index', :as => 'people'
|
287
|
+
end
|
288
|
+
localized do
|
289
|
+
match 'products', :to => 'products#index', :as => 'products'
|
290
|
+
end
|
291
|
+
end
|
292
|
+
config_default_locale_settings 'en'
|
293
|
+
|
294
|
+
@routes.translate_from_file(File.expand_path('locales/routes.yml', File.dirname(__FILE__)))
|
295
|
+
|
296
|
+
assert_routing '/es/gente', :controller => 'people', :action => 'index', :locale => 'es'
|
297
|
+
assert_routing '/es/productos', :controller => 'products', :action => 'index', :locale => 'es'
|
298
|
+
end
|
299
|
+
|
300
|
+
def test_not_localizing_routes_outside_blocks
|
301
|
+
@routes.draw do
|
302
|
+
localized do
|
303
|
+
match 'people', :to => 'people#index', :as => 'people'
|
304
|
+
end
|
305
|
+
match 'products', :to => 'products#index', :as => 'products'
|
306
|
+
end
|
307
|
+
config_default_locale_settings 'en'
|
308
|
+
|
309
|
+
@routes.translate_from_file(File.expand_path('locales/routes.yml', File.dirname(__FILE__)))
|
310
|
+
|
311
|
+
assert_routing '/es/gente', :controller => 'people', :action => 'index', :locale => 'es'
|
312
|
+
assert_routing '/products', :controller => 'products', :action => 'index'
|
313
|
+
assert_unrecognized_route '/es/productos', :controller => 'products', :action => 'index', :locale => 'es'
|
314
|
+
end
|
315
|
+
|
316
|
+
def test_action_controller_gets_locale_setter
|
317
|
+
ActionController::Base.instance_methods.include?('set_locale_from_url')
|
318
|
+
end
|
319
|
+
|
320
|
+
def test_action_controller_gets_locale_suffix_helper
|
321
|
+
ActionController::Base.instance_methods.include?('locale_suffix')
|
322
|
+
end
|
323
|
+
|
324
|
+
def test_action_view_gets_locale_suffix_helper
|
325
|
+
ActionView::Base.instance_methods.include?('locale_suffix')
|
326
|
+
end
|
327
|
+
|
328
|
+
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
class StubbedI18nBackend
|
2
|
+
@@translations = {
|
3
|
+
'es' => { 'people' => 'gente'},
|
4
|
+
'fr' => {} # empty on purpose to test behaviour on incompleteness scenarios
|
5
|
+
}
|
6
|
+
|
7
|
+
def self.translate(locale, key, options)
|
8
|
+
@@translations[locale.to_s][key] || options[:default]
|
9
|
+
rescue
|
10
|
+
options[:default]
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.available_locales
|
14
|
+
@@translations.keys
|
15
|
+
end
|
16
|
+
|
17
|
+
|
18
|
+
end
|
19
|
+
|
20
|
+
module RouteTranslator
|
21
|
+
module TestHelper
|
22
|
+
def path_string(route)
|
23
|
+
path = route.respond_to?(:path) ? route.path : route.to_s.split(' ')[1]
|
24
|
+
path.respond_to?(:spec) ? path.spec.to_s : path.to_s
|
25
|
+
end
|
26
|
+
|
27
|
+
def named_route(name)
|
28
|
+
@routes.routes.detect{ |r| r.name == name }
|
29
|
+
end
|
30
|
+
|
31
|
+
def formatted_root_route?
|
32
|
+
!(defined?(ActionPack) && ActionPack::VERSION::MAJOR == 3 && ActionPack::VERSION::MINOR > 0)
|
33
|
+
end
|
34
|
+
|
35
|
+
def assert_helpers_include(*helpers)
|
36
|
+
helpers.each do |helper|
|
37
|
+
['url', 'path'].each do |suffix|
|
38
|
+
[@controller, @view].each { |obj| assert_respond_to obj, "#{helper}_#{suffix}".to_sym }
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def assert_unrecognized_route(route_path, options)
|
44
|
+
assert_raise ActionController::RoutingError do
|
45
|
+
assert_routing route_path, options
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
metadata
ADDED
@@ -0,0 +1,83 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: route_translator
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Raul Murciano
|
9
|
+
- Enric Lluelles
|
10
|
+
autorequire:
|
11
|
+
bindir: bin
|
12
|
+
cert_chain: []
|
13
|
+
date: 2012-07-10 00:00:00.000000000 Z
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: mocha
|
17
|
+
requirement: !ruby/object:Gem::Requirement
|
18
|
+
none: false
|
19
|
+
requirements:
|
20
|
+
- - ! '>='
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: '0'
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
none: false
|
27
|
+
requirements:
|
28
|
+
- - ! '>='
|
29
|
+
- !ruby/object:Gem::Version
|
30
|
+
version: '0'
|
31
|
+
description: Translates the Rails routes of your application into the languages defined
|
32
|
+
in your locale files
|
33
|
+
email: enric@lluell.es
|
34
|
+
executables: []
|
35
|
+
extensions: []
|
36
|
+
extra_rdoc_files: []
|
37
|
+
files:
|
38
|
+
- .travis.yml
|
39
|
+
- Gemfile
|
40
|
+
- LICENSE
|
41
|
+
- README.md
|
42
|
+
- Rakefile
|
43
|
+
- gemfiles/Gemfile.rails-3.0.x
|
44
|
+
- gemfiles/Gemfile.rails-3.1.x
|
45
|
+
- lib/route_translator.rb
|
46
|
+
- lib/route_translator/route_set.rb
|
47
|
+
- lib/route_translator/route_set/dictionary_management.rb
|
48
|
+
- lib/route_translator/route_set/helpers.rb
|
49
|
+
- lib/route_translator/route_set/translator.rb
|
50
|
+
- lib/route_translator/version.rb
|
51
|
+
- lib/tasks/route_translator.rake
|
52
|
+
- route_translator.gemspec
|
53
|
+
- test/locales/routes.yml
|
54
|
+
- test/route_translator_test.rb
|
55
|
+
- test/test_helper.rb
|
56
|
+
homepage: http://github.com/enriclluelles/route_translator
|
57
|
+
licenses: []
|
58
|
+
post_install_message:
|
59
|
+
rdoc_options: []
|
60
|
+
require_paths:
|
61
|
+
- lib
|
62
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
63
|
+
none: false
|
64
|
+
requirements:
|
65
|
+
- - ! '>='
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: '0'
|
68
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
69
|
+
none: false
|
70
|
+
requirements:
|
71
|
+
- - ! '>='
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
version: '0'
|
74
|
+
requirements: []
|
75
|
+
rubyforge_project:
|
76
|
+
rubygems_version: 1.8.21
|
77
|
+
signing_key:
|
78
|
+
specification_version: 3
|
79
|
+
summary: Translate your Rails routes in a simple manner
|
80
|
+
test_files:
|
81
|
+
- test/locales/routes.yml
|
82
|
+
- test/route_translator_test.rb
|
83
|
+
- test/test_helper.rb
|