Localize.HTML.Hreflang (Localize Web v1.3.0)

Copy Markdown View Source

Generates rel="alternate" hreflang annotations.

An hreflang set is how a site tells search engines and agents which locale-specific variants of a page exist, and it is consumed rather than negotiated: nothing sends Accept-Language on the reader's behalf, so the declaration is the only signal.

Which is why it is validated here rather than emitted verbatim. A malformed annotation is silently ignored by every consumer, so the failure never shows up in production — the site simply looks monolingual. Every locale is therefore validated and rendered in its canonical BCP 47 form, and every URL must be fully qualified.

Summary

Functions

Builds link tags for a map of locale to URL.

Functions

links(alternates, options \\ [])

@spec links(
  map() | nil,
  keyword()
) :: {:ok, Phoenix.HTML.safe()} | {:error, Exception.t()}

Builds link tags for a map of locale to URL.

Arguments

  • alternates is a map of locale to fully-qualified URL. A locale may be any term Localize.validate_locale/1 accepts, or the string "x-default" to designate the fallback variant.

  • options is a keyword list of options.

Options

  • :canonicalize determines whether locales are rendered in canonical BCP 47 form — "es_MX" becomes "es-MX", "en-us" becomes "en-US". The default is true. Set it to false to emit exactly what was supplied.

Returns

  • {:ok, safe} where safe is rendered HTML, or

  • {:error, exception} if a locale is not recognised or a URL is not fully qualified.

Examples

iex> {:ok, {:safe, html}} = Localize.HTML.Hreflang.links(%{
...>   "en" => "https://example.com/",
...>   "de" => "https://example.com/de/"
...> })
iex> IO.iodata_to_binary(html) =~ ~s|hreflang="de"|
true

# Underscores are canonicalised; BCP 47 requires a hyphen
iex> {:ok, {:safe, html}} = Localize.HTML.Hreflang.links(%{"es_MX" => "https://example.com/mx/"})
iex> IO.iodata_to_binary(html) =~ ~s|hreflang="es-MX"|
true

# A locale that does not exist is an error, not silent bad markup
iex> Localize.HTML.Hreflang.links(%{"es-SP" => "https://example.com/es/"})
{:error, %Localize.InvalidLocaleError{locale_id: "es-SP"}}

# So is a relative URL, which every consumer ignores
iex> {:error, error} = Localize.HTML.Hreflang.links(%{"de" => "/de/"})
iex> error.__struct__
Localize.RelativeUrlError