Création d'itinéraires avec un préfixe de chemin facultatif
-
03-07-2019 - |
Question
Comment puis-je faire en sorte que mes itinéraires reconnaissent un paramètre de préfixe facultatif comme suit:
/*lang/controller/id
En ce que la partie lang est facultative et a une valeur par défaut si elle n'est pas spécifiée dans l'URL:
/en/posts/1 => lang = en
/fr/posts/1 => lang = fr
/posts/1 => lang = en
EDIT
Idéalement, je souhaite effectuer cette opération sur plusieurs contrôleurs et actions en mappant un espace de noms:
map.namespace "*lang" do |lang|
lang.resources :posts
lang.resources :stories
end
La solution
OK, j'ai réussi à résoudre ce problème:
Il n’ya aucun moyen de faire cela dans Rails par défaut (du moins, pas encore). Au lieu d'utiliser des espaces de noms et des valeurs par défaut, je devais installer le filtre de routage de Sven Fuchs . .
Une fois le plugin installé, j'ai ajouté le fichier suivant à mon répertoire lib:
require 'routing_filter/base'
module RoutingFilter
class Locale < Base
# remove the locale from the beginning of the path, pass the path
# to the given block and set it to the resulting params hash
def around_recognize(path, env, &block)
locale = nil
path.sub! %r(^/([a-zA-Z]{2})(?=/|$)) do locale = $1; '' end
returning yield do |params|
params[:locale] = locale || 'en'
end
end
def around_generate(*args, &block)
locale = args.extract_options!.delete(:locale) || 'en'
returning yield do |result|
if locale != 'en'
result.sub!(%r(^(http.?://[^/]*)?(.*))){ "#{$1}/#{locale}#{$2}" }
end
end
end
end
end
J'ai ajouté cette ligne à routes.rb:
map.filter 'locale'
Ceci complète essentiellement un hook avant et après, généré par le plugin, qui encapsule le routage des rails.
Quand une URL est reconnue, et avant que Rails ne puisse faire quoi que ce soit avec elle, la méthode around_recognize est appelée. Ceci extraira un code de deux lettres représentant les paramètres régionaux et le transmettra dans les paramètres, par défaut à 'en' si aucun paramètre régional n'est spécifié.
De même, lorsqu'une URL est générée, le paramètre de paramètres régionaux sera inséré dans l'URL à gauche.
Cela me donne les URL et les mappages suivants:
/ => :locale => 'en'
/en => :locale => 'en'
/fr => :locale => 'fr'
Tous les helpers d'URL existants fonctionnent comme avant, la seule différence étant que, à moins que les paramètres régionaux ne soient spécifiés, ils sont préservés:
home_path => /
home_path(:locale => 'en') => /
home_path(:locale => 'fr') => /fr
Autres conseils
Vous pouvez définir des valeurs par défaut dans une route à l’aide de la touche : defaults
. Essayez ceci:
map.connect ':lang/posts/:id', :controller => 'posts', :action => 'show',
:defaults => { :lang => 'en' }
Je comprends que cette vieille question, mais elle peut être utile.
map.with_options(:path_prefix => ":locale") do |m|
m.resources :posts
m.resources :stories
end
Et vous devez ajouter un filtre avant le contrôleur d'application pour définir les paramètres régionaux, tels que
before_filter :define_locale
def define_locale
if params[:locale] == nil
I18n.locale = 'en'
else
I18n.locale = params[:locale]
end
end
Je devine (pas le temps de tester pour le moment) que cela pourrait fonctionner:
map.connect ':language/posts/:id', :controller => 'posts', :action => 'show'
map.connect 'posts/:id', :controller => 'posts', :action => 'show'
OK, essayé - cela fonctionne, du moins sur Rails 2.1.1. Donc c'est bien. Je ne parviens pas à faire fonctionner l’idée: par défaut, ce qui est dommage, car c’est DRYer.
Je pensais que vous pourriez utiliser à la fois une [clé] = > nil pour spécifier un paramètre facultatif. Quelque chose comme:
map.connect ':lang/posts/:id', :controller => 'posts', :action => 'show', :lang => nil