Pregunta

¿Cómo puedo hacer que mis rutas reconozcan un parámetro de prefijo opcional de la siguiente manera?

/*lang/controller/id

En que la parte lang es opcional y tiene un valor predeterminado si no se especifica en la URL:

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

EDIT

Idealmente, estoy buscando hacer esto en muchos controladores y acciones al asignar un espacio de nombres:

map.namespace "*lang" do |lang|
  lang.resources :posts
  lang.resources :stories
end
¿Fue útil?

Solución

OK, he logrado solucionar este problema:

No hay forma de hacer esto en Rails por defecto (al menos, todavía no). En lugar de usar espacios de nombres y valores predeterminados, necesitaba instalar filtro de enrutamiento de Sven Fuchs .

Una vez que se instala el complemento, agregué 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

Agregué esta línea a routes.rb:

map.filter 'locale'

Esto básicamente llena un gancho antes y después, generado por el complemento, que envuelve el enrutamiento de los rieles.

Cuando se reconoce una url, y antes de que Rails pueda hacer 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á a través de los parámetros, por defecto a 'en' si no se especifica una 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 URL 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

Otros consejos

Puede definir los valores predeterminados en una ruta usando la tecla : defaults . Prueba esto:

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

Entiendo que esta vieja pregunta, pero puede ser útil.

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

Y debe agregar antes del filtro al controlador de la 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

Supongo (no hay tiempo para probar ahora) 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é, funciona, al menos en Rails 2.1.1. Así que eso es bueno. Sin embargo, no se puede hacer funcionar la idea de: por defecto, lo cual es una pena, porque es SECADOR.

Pensé que al mismo tiempo podría usar una [clave] = > nil para especificar un parámetro opcional. Algo así como:

map.connect ':lang/posts/:id', :controller => 'posts', :action => 'show', :lang => nil
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top