2008-10-17 24 views
22

¿Cómo puedo ir sobre la fabricación de mis rutas reconocen un parámetro prefijo opcional de la siguiente manera:Creación de rutas con un prefijo de ruta opcional

/*lang/controller/id 

porque la parte lang es opcional, y tiene un valor por defecto si no se especifica en la URL:

/en/posts/1 => lang = en 
/fr/posts/1 => lang = fr 
/posts/1  => lang = en 

EDITAR

lo ideal es que estoy buscando para hacer esto a través de muchos controladores y acciones mediante la asignación de una espacio de nombres:

map.namespace "*lang" do |lang| 
    lang.resources :posts 
    lang.resources :stories 
end 
+0

En su ejemplo sólo de referencia 1 controlador, pero lo tomo desea crear esta ruta para cada ¿controlador? –

Respuesta

19

bien, he logrado solucionar este problema:

no hay manera de hacer esto en Rails por defecto (al menos, no todavía). En lugar de usar espacios de nombres y valores predeterminados, necesitaba instalar Sven Fuchs' routing filter.

Una vez instalado el plugin, que añade el siguiente archivo a mi directorio 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 

añadí esta línea para routes.rb:

map.filter 'locale' 

Esto básicamente rellena un antes y after hook, generado por el complemento, que envuelve el enrutamiento de los rieles.

Cuando se reconoce una url y antes de que Rails haga algo con ella, se llama al método around_recognize. Esto extraerá un código de dos letras que representa la configuración regional, y lo pasará en los parámetros, por defecto a 'en' si no se especifica la configuración regional.

Del mismo modo, cuando se genera una url, el parámetro de configuración regional se insertará en la URL en el lado izquierdo.

Esto me da las siguientes direcciones y asignaciones:

/ => :locale => 'en' 
/en => :locale => 'en' 
/fr => :locale => 'fr' 

Todos los ayudantes de URL existentes funcionan como antes, con la única diferencia de que a menos que se especifique la configuración regional, se conserva:

home_path     =>/
home_path(:locale => 'en') =>/
home_path(:locale => 'fr') => /fr 
+2

Gracias por la sugerencia, esto funcionó muy bien para algunos trabajos de traducción/localización/internacionalización I 'Estoy haciendo. FYI, no tiene que agregar ese archivo a su biblioteca: el filtro 'locale' ya está incluido en el complemento. Todo lo que debe hacer es: 1. Instale el complemento. 2. Agregue 'map.filter 'locale'' a sus routes.rb. ¡Después de eso, simplemente comienza a funcionar! Bonito. También agregué 'RoutingFilter :: Locale.include_default_locale = false' a mi environment.rb para evitar'/en' estar en mis enlaces. Funciona muy bien, espero que el plugin de Sven se arrastre al código base de Rails I18n. –

+1

Aquí hay otra opción que encontré hoy, no la he examinado (el filtro de enrutamiento funciona muy bien) pero podría ser de interés para otros: http://github.com/raul/translate_routes –

+0

Cualquier idea sobre cómo traducir esto en Rails3? – dgilperez

1

supongo (no hay tiempo para poner a prueba en este momento) que esto podría funcionar:

map.connect ':language/posts/:id', :controller => 'posts', :action => 'show' 
map.connect 'posts/:id', :controller => 'posts', :action => 'show' 

bien, lo intentó - que funciona, en los carriles 2.1.1 por lo menos. Así que eso es bueno. Sin embargo, no se puede lograr que funcione la idea de los valores predeterminados, lo cual es una pena, porque es DRYer.

2

Puede definir los valores predeterminados en una ruta utilizando la clave :defaults. Intente esto:

map.connect ':lang/posts/:id', :controller => 'posts', :action => 'show', 
           :defaults => { :lang => 'en' } 
+0

No funciona en 2.1.1 en mi máquina. http: // localhost: 3000/posts/1 da Sin ruta coincide "/ posts/1" con {: method =>: get} Parece que: los valores predeterminados solo proporcionan parámetros que no están en la ruta? Necesito investigar: no sabía nada sobre: ​​valores predeterminados, ¡así que gracias! –

+0

Creo que está en el camino correcto: ¿es posible integrar esta opción con espacios de nombres y recursos? – Codebeef

+1

IIRC, los valores predeterminados funcionan como valores predeterminados en los parámetros del método, es decir, los valores predeterminados solo se pueden usar en los últimos valores cuando se enumeran en orden, no en los primeros valores –

1

Pensé que podría utilizar una vez [a] => nil para especificar un parámetro opcional. Algo así como:

map.connect ':lang/posts/:id', :controller => 'posts', :action => 'show', :lang => nil 
2

Entiendo esta vieja pregunta, pero puede ser útil.

map.with_options(:path_prefix => ":locale") do |m| 
    m.resources :posts 
    m.resources :stories   
    end 

Y hay que añadir antes del filtro de controlador de aplicación para definir la configuración regional, como

before_filter :define_locale 

def define_locale 
    if params[:locale] == nil 
    I18n.locale = 'en' 
    else 
    I18n.locale = params[:locale] 
    end 
end 
+1

El prefijo de ruta no es opcional, por lo que siempre debe proporcionar una configuración regional a menos que duplique las rutas fuera del bloque. – dseifert

Cuestiones relacionadas