A Simple Strategy for Translated Routes in Rails

The streets of Guatapé, Antioquia, Colombia

Photo by Daniel Vargas on Unsplash

Recently I've been working on a new project, a job board focused on remote offerings. Admittedly this is not a novel idea, however I haven't seen anything like this targeted to the local job market in Colombia. My guess is that remote offerings are not that popular here (yet) and that most of the existing boards out there are not in spanish so I decided to give it a try.

I decided to go with Rails for the stack since it would allow me to leverage ActiveStorage for file uploads and ActionText for rich text editing, both of which I was going to need at some point for this.

My hypothesis is that current remote job boards haven't caught on due to them being on a foreign language, so I want this app to be completely in spanish. Rails comes with built in i18n, however it is targetted at content and does not cover one piece of the app, the URL. Also, I'm not really looking to internationalize this app I just want the public routes not to be in english.

Also, I'm not really looking to support multiple languages or internationalize this app, I just want the public facing routes not to be in english.

In the past, I've dealt with this in the following ways:

None of this options seemed very satisfying to me. There must be a simpler way to achieve this. After all, Rails is known for being a modular and flexible framework, although some people might argue with this statement.

Turns out there is a simpler way and it had been in front of me all along. I just needed to take a closer look into how rails routing works. When you define a resource or route in rails, it can take some keyword arguments. One of them is path, which according to the docs it allows you to change the path prefix of the resource. So we could do something like:

resources :jobs, path: 'trabajos'
# Generates the following routes:
# jobs GET /trabajos(.:format)
# POST /trabajos(.:format)
# new_job GET /trabajos/new(.:format)
# edit_job GET /trabajos/:id/edit(.:format)
# job GET /trabajos/:id(.:format)
# PATCH /trabajos/:id(.:format)
# PUT /trabajos/:id(.:format)
# DELETE /trabajos/:id(.:format)

That's great, on the one hand we have now have our user facing routes (mostly) in Spanish and on the other hand we get to keep our code consistent by referring to the models in English in our route helpers.

What about new and edit? Well it turns out that Rails also has an option to override those with the path_names keyword:

resources :jobs, path: 'trabajos', path_names: {new: "nuevo", edit: "editar"}

Furthermore, we could avoid having to pass path_names to every resource by defining a scope at the top of our routes:

scope(:path_names => { :new => 'nuevo', :edit => 'editar' }) do
resources :jobs, path: 'trabajos'
resources :tags, path: 'etiquetas'
# new_job GET /trabajos/nuevo(.:format)
# edit_job GET /trabajos/:id/editar(.:format)

And there you go! now every part of the URL should be in your language of choice, withouot having to include complex external dependencies or sacrificing hypothetical SEO points.

I hope this simple example is useful enough to illustrate that sometimes a simple solution might be enough and you sometimes have to look into the framework and the options it provides, instead of outside for dependencies that often include broader use cases.