-
Notifications
You must be signed in to change notification settings - Fork 143
Generating translated URLs
Geremia Taglialatela edited this page Sep 1, 2022
·
7 revisions
The following syntax may generate localized URLs in all available locales to link alternative versions of the current page for basic use cases:
<% I18n.available_locales.each do |locale| %>
<%= link_to locale, url_for(locale: locale.to_s, only_path: true), rel: 'alternate', hreflang: locale.to_s %>
<% end %>
The only_path
option generates relative URLs instead of absolute ones.
HEADS-UP!
- The
locale
symbol must be converted to string (locale.to_s
) -
url_for
is subject to limitations of Rails'url_for
, so it may not work for all use cases (ref: #269)
To generate URL for a different page you can specify controller's action in the url_for
call:
url_for(controller: '...', action: '...', locale: '...', only_path: true)
Localized slugs needs extra code, and you will need a custom implementation to deal with this use case.
This paragraph provides some example approaches. Feel free to move this code where you think it belongs (helpers, presenters...) and please edit this wiki if you have better suggestions.
Let's say we have the following:
# app/controllers/articles_controller.rb
class ArticlesController < ApplicationController
before_action :set_article, only: :show
private
def set_article
@article = Article.friendly.find(params[:id])
end
end
# app/models/article.rb
class Article < ApplicationRecord
extend FriendlyId
translates :title, :slug
friendly_id :title, use: %i[globalize slugged]
end
# config/routes.rb
Rails.application.routes.draw do
# For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
localized do
resources :articles, only: %i[index show]
end
end
# app/controllers/articles_controller
class ArticlesController < ApplicationController
before_action :set_article, only: :show
append_before_action :set_localized_urls, only: :show
private
def set_article
@article = Article.friendly.find(params[:id])
end
def set_localized_urls
@localized_urls = I18n.available_locales.each_with_object({}) do |locale, obj|
obj[locale] = I18n.with_locale(locale) { article_path(@article) }
end
end
end
<!-- app/views/articles/show.html.erb -->
<dl>
<% @localized_urls.each do |locale, url| %>
<dt><%= locale.to_s %></dt>
<dd><%= link_to url, url, rel: 'alternate', hreflang: locale.to_s %></dd>
<% end %>
</dl>
<!-- app/views/articles/show.html.erb -->
<dl>
<% I18n.available_locales.each do |locale| %>
<dt><%= locale.to_s %></dt>
<dd><%= I18n.with_locale(locale) { link_to url_for(@article), url_for(@article), rel: 'alternate', hreflang: locale.to_s } %></dd>
<% end %>
</dl>
<!-- app/views/articles/show.html.erb -->
<dl>
<% I18n.available_locales.each do |locale| %>
<dt><%= locale.to_s %></dt>
<dd><%= I18n.with_locale(locale) { link_to article_path(@article), article_path(@article), rel: 'alternate', hreflang: locale.to_s } %></dd>
<% end %>
</dl>
Ref: