DEV Community

Iago Angelim Costa Cavalcante
Iago Angelim Costa Cavalcante

Posted on

4 1

Phoenix Internationalization

Problem

You need to internationalize your website. You decide to use gettext and your system uses LiveView. Everything you find seems too complicated or doesn't easily meet your needs without a lot of configuration.

How can we use LiveSession to take care of our application's i18n?

Solution

With LiveView 0.18 we can have functional components and easily trigger an event from our functional component and intercept them in a general way using LiveSession.

This was the simplest approach I could think of to share and modify the language of the page we are accessing.

With a global assign, we can access the current locale and modify the language of the page using the with_locale from gettext.

Attempt

First, we need to define a second language for our i18n tool (gettext). To do this, simply go to your project directory through the terminal and run the following command:

mix gettext.merge priv/gettext --locale pt_BR
Enter fullscreen mode Exit fullscreen mode

The chosen language was pt_BR, but it can be any available language you want to use.

With our new language set, we will now create our live session that will take care of setting our default language in the assigns for all live views and will have the method to handle language switching in the system.

Inside our _web folder, we will create a module called locale.ex, and it will have the following structure:

defmodule PhoenixI18nWeb.Locale do
  import Phoenix.LiveView
  use Phoenix.Component

  def on_mount(:default, _params, _session, socket) do

    {:cont,
     socket
     |> assign(:locale, "en")
     |> attach_hook(:set_locale, :handle_event, &handle_event/3)}
  end

  defp handle_event("toggle_locale", %{"locale" => "en"}, socket) do
    locale = "pt_BR"
    perform_assigns(socket, locale)
  end

  defp handle_event("toggle_locale", %{"locale" => "pt_BR"}, socket) do
    locale = "en"
    perform_assigns(socket, locale)
  end

  defp handle_event(_, _, socket) do
    {:cont, socket}
  end

  defp perform_assigns(socket, locale) do
    Gettext.put_locale(IagocavalcanteWeb.Gettext, locale)
    {:halt, socket |> assign(locale: locale)}
  end
end
Enter fullscreen mode Exit fullscreen mode

In the on_mount function, we are setting the default locale to English and we have a hook that will be responsible for handling the language change event. We call it toggle_locale.

With this done, we are ready to create our component that will call the hook that was added to the mount. It will have the following structure:

defmodule PhoenixI18nWeb.ToggleLocale do
  use Phoenix.Component

  def toggle_locale(assigns) do
    ~H"""
    <button
      phx-click="toggle_locale"
      phx-value-locale={@locale}
      type="button"
      aria-label="Toggle locale"
      class="group rounded-full bg-white/90 px-3 py-2 shadow-lg shadow-zinc-800/5 ring-1 ring-zinc-900/5 backdrop-blur transition dark:bg-zinc-800/90 dark:ring-white/10 dark:hover:ring-white/20"
    >
      <img
        src={"/images/flags/#{@locale}.png"}
        class="h-6 w-6 fill-zinc-700 stroke-zinc-500 transition dark:fill-teal-400/10 dark:stroke-teal-500"
      />
    </button>
    """
  end
end
Enter fullscreen mode Exit fullscreen mode

With this, now we just need to update our live view and add wherever we want to use Gettext with the chosen language the following code:

<%= Gettext.with_locale(@locale, fn -> %>
  <%= gettext("Peace of mind from prototype to production.") %>
<% end) %>
Enter fullscreen mode Exit fullscreen mode

Finally, let's add our live session to the routes that we need to take care of for i18N:

live_session :locale, on_mount: [PhoenixI18nWeb.RestoreLocale] do
  live "/", HomeLive, :home
end
Enter fullscreen mode Exit fullscreen mode

Image of Datadog

Create and maintain end-to-end frontend tests

Learn best practices on creating frontend tests, testing on-premise apps, integrating tests into your CI/CD pipeline, and using Datadog’s testing tunnel.

Download The Guide

Top comments (0)

👋 Kindness is contagious

Explore a sea of insights with this enlightening post, highly esteemed within the nurturing DEV Community. Coders of all stripes are invited to participate and contribute to our shared knowledge.

Expressing gratitude with a simple "thank you" can make a big impact. Leave your thanks in the comments!

On DEV, exchanging ideas smooths our way and strengthens our community bonds. Found this useful? A quick note of thanks to the author can mean a lot.

Okay