How to put lang in html element in Routex?

The basic routing with Routex and Liveview works so I have / for English /fr for French etc.

But the html source show en for everything:

<html lang="en">
  <head>
    <meta charset="utf-8" />

I want lang=”fr” for French content.

I guess I need to modify root.html.heex template but not sure how.

I came up with this:

lang={Gettext.get_locale()}

but I am not sure if it is ok or there is a different way to do this.

Any Phoenix users who know how to do this correctly?

Using the default config and Phoenix 1.8, I guess you can just use the assign found in the configuration:

In config:
assigns: %{namespace: :rtx, attrs: [:locale, :language, :region]},

In template:
lang={@rtx.language}

Please let me know if it works for you, then we can add it to the documentation.


The Gettext-variant also works because the language of Gettext is set to the same value as the attribute by the Runtime Dispatcher . However it might not be the language of the route (see explanation below).

I recommend to use the attribute, as there are more attributes you can use in your templates such as @rtx.language_display_name and @rtx.region_display_name. Just add them to the config key assigns: to make them available.


Explanation

  1. Attributes are added as metadata to routes by extensions such as the Localize Phoenix Routes extension.

Then, two other plugins use that data:

2.1 The configured subset of attributes are added to the assigns and so accessible as @rtx.language. This is done by the Assigns extension

2.2 The attribute can be used (and is by default) by Phoenix Runtime extension to set @rtx.runtime.language. This might be the language of the route, it might not. You decide (see manpage)

2.2.1 The @rtx.runtime.language is then used by Runtime Dispatcher as an argument for Gettext.put_locale/1. Again, this is not guaranteed to be the language of the route.

So now there are two assigns you should be aware of:
@rtx.language is the language attached to the route at compile time.
@rtx.runtime.language is the language detected at runtime.
Why the distinction?

2 Likes

Yes, it seems to be working with {@rtx.language} as well. Thanks.

Using the default config you can just use

  • @rtx.language to insert the language of the route
  • @rtx.runtime.language to insert the runtime detected language (which can com from a variety of sources. (see below)

In-Depth Explanation

This explanation is for those wanting to understand how extensions collaborate. All the examples use the ‘standard configuration’ as shown in the Usage Guide.

  1. Each extension can add Routex.Attrs metadata to routes. For example, the Localize Phoenix Routes extension adds values for :locale, :region and a few others.
  2. Other extensions can use the shared metadata. Fox example: the Assigns extension adds locale metadata to the socket assigns. Making @rtx.language available.
  3. The Phoenix Runtime extension also uses the metadata of the route, but as a last resort when other values are not found, to set @rtx.runtime.language. So this value might be the language of the route but probably is the preferred language of the browser.
  4. The @rtx.runtime.language is used by Runtime Dispatcher as an argument for Gettext.put_locale/1. Again, this is not guaranteed to be the language of the route.

So there are two values you should be aware of:

@rtx.language is the language attached to the route at compile time.
@rtx.runtime.language is the language detected at runtime.

The reason for the distinction is explained at
Localization vs Translation: Why Your Website Should Keep Them Separate


Using Gettext.get_locale

The Gettext-variant also works because the language of Gettext is set to the same value as the attribute by the Runtime Dispatcher.

I recommend to use the attribute though, as there are more attributes you can use in your templates such as @rtx.language_display_name and @rtx.region_display_name. Just add them to the config key assigns: to make them available. Not to mention these are immutable instead of Gettext mutable state.