summaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
Diffstat (limited to 'app')
-rw-r--r--app/helpers/social_helper.rb53
-rw-r--r--app/views/layouts/_social_meta.html.erb7
2 files changed, 56 insertions, 4 deletions
diff --git a/app/helpers/social_helper.rb b/app/helpers/social_helper.rb
index d6932a2f..e43f5a5c 100644
--- a/app/helpers/social_helper.rb
+++ b/app/helpers/social_helper.rb
@@ -92,11 +92,14 @@ module SocialHelper
92 @page&.published_at&.iso8601 92 @page&.published_at&.iso8601
93 end 93 end
94 94
95 # request.path rather than a routing helper: it is already the locale's 95 # The address of the version actually being served, not of the URL that
96 # own canonical form -- unprefixed for German, /en/ for English -- and 96 # was requested. So /de/updates/foo points at /updates/foo, and a page
97 # dropping the query string is what makes it canonical. 97 # with no English translation requested under /en/ points at the German
98 # URL rather than claiming to be an English page. The query string is
99 # dropped, which is what makes it canonical.
98 def og_canonical_url 100 def og_canonical_url
99 og_absolute_url(request.path) 101 locale = @page&.persisted? ? og_locale_key : I18n.locale
102 og_locale_url(locale)
100 end 103 end
101 104
102 def og_locale 105 def og_locale
@@ -104,6 +107,48 @@ module SocialHelper
104 OG_LOCALES[I18n.default_locale.to_sym]) 107 OG_LOCALES[I18n.default_locale.to_sym])
105 end 108 end
106 109
110 # Locales that can appear in a URL. Cccms::LOCALES will replace this when
111 # the set_locale allowlist lands; :root is in available_locales but is not
112 # a language.
113 def og_url_locales
114 I18n.available_locales - [:root]
115 end
116
117 # The request path with any locale prefix stripped, so a locale-specific
118 # URL can be rebuilt from it. /en/updates/foo, /de/updates/foo and
119 # /updates/foo all reduce to /updates/foo.
120 def og_bare_path
121 pattern = og_url_locales.join("|")
122 request.path.sub(%r{\A/(?:#{pattern})(?=/|\z)}, "").presence || "/"
123 end
124
125 # Absolute URL for this page in one locale. The default locale is
126 # unprefixed, matching default_url_options, so /updates/foo is the
127 # canonical German address and /de/updates/foo is a duplicate of it.
128 def og_locale_url(locale)
129 locale = locale.to_sym
130 locale = I18n.default_locale unless og_url_locales.include?(locale)
131
132 path = og_bare_path
133 return og_absolute_url(path) if locale == I18n.default_locale
134
135 og_absolute_url(path == "/" ? "/#{locale}" : "/#{locale}#{path}")
136 end
137
138 # One entry per locale in which the page genuinely has a translation,
139 # including a self-reference, which Google requires. A locale with no
140 # translation is omitted: /en/ would render German content through the
141 # fallback chain, which is not an English version of the page. With only
142 # one translation there is nothing to declare.
143 def og_hreflang_alternates
144 return [] unless @page&.persisted?
145
146 locales = @page.translated_locales.map(&:to_sym) & og_url_locales
147 return [] if locales.size < 2
148
149 locales.sort.map { |locale| [locale.to_s, og_locale_url(locale)] }
150 end
151
107 # Only locales in which this page genuinely has a translation, so a 152 # Only locales in which this page genuinely has a translation, so a
108 # crawler is not told about a variant that would fall back. 153 # crawler is not told about a variant that would fall back.
109 def og_locale_alternates 154 def og_locale_alternates
diff --git a/app/views/layouts/_social_meta.html.erb b/app/views/layouts/_social_meta.html.erb
index 9a86d26d..36547d26 100644
--- a/app/views/layouts/_social_meta.html.erb
+++ b/app/views/layouts/_social_meta.html.erb
@@ -23,6 +23,13 @@
23 <meta property="og:locale:alternate" content="<%= alternate %>"/> 23 <meta property="og:locale:alternate" content="<%= alternate %>"/>
24 <% end %> 24 <% end %>
25 25
26 <% if (hreflang_alternates = og_hreflang_alternates).any? %>
27 <% hreflang_alternates.each do |code, url| %>
28 <link rel="alternate" hreflang="<%= code %>" href="<%= url %>"/>
29 <% end %>
30 <link rel="alternate" hreflang="x-default" href="<%= og_locale_url(I18n.default_locale) %>"/>
31 <% end %>
32
26 <% if og_published_time %> 33 <% if og_published_time %>
27 <meta property="article:published_time" content="<%= og_published_time %>"/> 34 <meta property="article:published_time" content="<%= og_published_time %>"/>
28 <% end %> 35 <% end %>