Skip to content

Instantly share code, notes, and snippets.

@genaromadrid
Last active December 9, 2016 17:21
Show Gist options
  • Save genaromadrid/3ca890233f9c46cdf09b655133e5dadd to your computer and use it in GitHub Desktop.
Save genaromadrid/3ca890233f9c46cdf09b655133e5dadd to your computer and use it in GitHub Desktop.
A really small library to translate routes for better SEO
class RouteTranslator
def self.routes(rails_router, &block)
RouteTranslator.new(rails_router).instance_eval(&block)
end
def initialize(rails_router)
@rails_router = rails_router
end
def get(route, options)
redirect = options.key?(:redirect) ? options[:redirect] : true
options.delete(:redirect)
I18n.available_locales.each do |loc|
rails_router.scope loc, defaults: { locale: loc } do
rails_router.get(translate_route(route, loc), options.merge(as: "#{options[:as] || route}_#{loc}"))
end
end
return unless redirect
I18n.available_locales.each do |loc|
translated = translate_route(route, loc)
rails_router.get(translated, to: rails_router.redirect("#{loc}/#{translated}"))
end
end
private
attr_reader :rails_router
def translate_route(route, locale)
path = "routes.#{route}"
unless I18n.exists?(path, locale)
fail "you need to define '#{locale}::routes::#{route}' in your 'routes.yml'"
end
I18n.t(path, locale: locale)
end
end
@genaromadrid
Copy link
Author

genaromadrid commented Dec 9, 2016

Acording to SEO best practices you should translate the URLs for multilingual sites. To do that in rails you have to add a lot of lines to your routes.rb. For example if you have prices and questions in two languages you'd have something like this:

# routes.rb
get 'questions', to: redirect('en/questions')
get 'prices', to: redirect('en/prices')

scope :en, defaults: { locale: :es } do
  get 'questions', to: 'home#questions', as: :questions_en
  get 'prices', to: 'home#prices', as: :prices_en
end

get 'preguntas', to: redirect('es/preguntas')
get 'precios', to: redirect('es/precios')

scope :es, defaults: { locale: :es } do
  get 'preguntas', to: 'home#questions', as: :questions_es
  get 'precios', to: 'home#prices', as: :prices_es
end 

The redirect is for users langing in /prices to be redirect to /en/prices

This library allows you to do the exact same thing with 4 lines of code in your routes.rb and some in your config/locales folder:

# routes.rb
LanguageRoutes.routes(self) do
  get :questions, to: 'home#questions'
  get :prices, to: 'home#prices'
end
# config/locales/routes.yml
en:
  routes:
    questions: questions
    prices: prices
es:
  routes:
    questions: preguntas
    prices: precios

Which will generate:

   questions_es GET  /es/preguntas(.:format)   home#questions {:locale=>:es}
   questions_en GET  /en/questions(.:format)   home#questions {:locale=>:en}
      preguntas GET  /preguntas(.:format)      redirect(301, es/preguntas)
      questions GET  /questions(.:format)      redirect(301, en/questions)
      prices_es GET  /es/precios(.:format)     home#prices {:locale=>:es}
      prices_en GET  /en/prices(.:format)      home#prices {:locale=>:en}
        precios GET  /precios(.:format)        redirect(301, es/precios)
         prices GET  /prices(.:format)         redirect(301, en/prices)

That's it

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment