View Source Cldr.Routes (Cldr Routes v1.3.0)

Generate localized route generation, locaverified routes and route helper modules.

This module when used , provides a localize/1 macro that is designed to wrap the standard Phoenix route macros such as get/3, put/3 and resources/3 and localizes them for each locale defined in a Gettext backend module attached to a Cldr backend module.

Translations for the parts of a given route path are translated at compile-time and are then combined into a localised route that is added to the standard Phoenix routing framework.

As a result, users can enter URLs using localised terms which can enhance user engagement and content relevance.

Similarly, localised path and URL helpers are generated that wrap the standard Phoenix helpers to supporting generating localised paths and URLs.

Configuration

A Cldr backend module that configures a Gettext asosciated backend is required.

Path parts (the parts between "/") are translated at compile time using Gettext. Therefore localization can only be applied to locales that are defined in a gettext backend module that is configured in a Cldr backend module.

For example:

defmodule MyApp.Cldr do
  use Cldr,
    locales: ["en", "fr"],
    default_locale: "en".
    gettext: MyApp.Gettext
    providers: [Cldr.Routes]

end

Here the MyApp.Cldr backend module is used to instrospect the configured locales in order to drive the localization generation.

Next, configure the router module to use the localize/1 macro by adding use MyApp.Cldr.Route to the module and invoke the localize/1 macro to wrap the required routes. For example:

defmodule MyApp.Router do
  use Phoenix.Router
  use MyApp.Cldr.Routes

  localize do
    get "/pages/:page", PageController, :show
    resources "/users", UserController
  end
end

The following routes are generated in the MyApp.Router module (assuming that translations are updated in the Gettext configuration).

For this example, the :fr and :de translations are the same as the :en text with _fr or _de appended.

% mix phx.routes MyApp.Router
page_de_path  GET     /pages_de/:page     PageController :show
page_en_path  GET     /pages/:page        PageController :show
page_fr_path  GET     /pages_fr/:page     PageController :show
user_de_path  GET     /users_de           UserController :index
user_de_path  GET     /users_de/:id/edit  UserController :edit
user_de_path  GET     /users_de/new       UserController :new
user_de_path  GET     /users_de/:id       UserController :show
...

It is also possible to emit the routes and route helpers before localization using the mix phx.routes task on an automatically generated mini-router. See h MyApp.Router.LocalizedRoutes.

Interpolating Locale Data

A route may be defined with elements of the locale interpolated into it. These interpolations are specified using the normal #{} interpolation syntax. However since route translation occurs at compile time only the following interpolations are supported:

  • locale will interpolate the Cldr locale name
  • language will interpolate the Cldr language name
  • territory will interpolate the Cldr territory code

Some examples are:

localize do
  get "/#{locale}/locale/pages/:page", PageController, :show
  get "/#{language}/language/pages/:page", PageController, :show
  get "/#{territory}/territory/pages/:page", PageController, :show
end

Localized Helpers

Manually constructing the localized helper names shown in the example above would be tedious. Therefore a LocalizedHelpers module is generated at compile-time. Assuming the router module is called MyApp.Router then the full name of the localized helper module is MyApp.Router.LocalizedHelpers.

As of Phoenix 1.7, a Helpers module is generrated by default but this behaviour can be disabled by adding helpers: false to the use Phoenix.Router call. The same is true of localized helpers. They will be generated by default but can be disabled by adding helpers: false to the use MyApp.Cldr.Routes line in your router module.

The functions on this module are the non-localized versions. Localised routes can be printed by leveraging the phx.routes mix task. For example:

% mix phx.routes MyApp.Router
page_de_path  GET      /pages_de/:page     PageController :show
page_en_path  GET      /pages/:page        PageController :show
page_fr_path  GET      /pages_fr/:page     PageController :show
user_de_path  GET      /users_de           UserController :index
user_de_path  GET      /users_de/:id/edit  UserController :edit
user_de_path  GET      /users_de/new       UserController :new
user_de_path  GET      /users_de/:id       UserController :show
user_de_path  POST     /users_de           UserController :create
user_de_path  PATCH    /users_de/:id       UserController :update
              PUT   /users_de/:id       UserController :update
.....

The functions on the MyApp.Router.LocalizedHelpers module all respect the current locale, based upon Cldr.get_locale/1, and will delegate to the appropriate localized function in the MyApp.Router.Helpers module created automatically by Phoenix at compile time.

Configuring Localized Helpers as default

Since LocalizedHelpers have the same semantics and API as the standard Helpers module it is possible to update the generated Phoenix configuration to use the LocalizedHelpers module by default. Assuming the presence of myapp_web.ex defining the module MyAppWeb then changing the view_helpers function from

defp view_helpers do
  quote do
    ...

    import MyAppWeb.ErrorHelpers
    import MyAppWeb.Gettext
    alias MyAppWeb.Router.Helpers, as: Routes
  end
end

to

defp view_helpers do
  quote do
    ...

    import MyAppWeb.ErrorHelpers
    import MyAppWeb.Gettext
    alias MyAppWeb.Router.LocalizedHelpers, as: Routes
  end
end

will result in the automatic use of the localized helpers rather than the standard helpers.

Translations

In order for routes to be localized, translations must be provided for each path segment. This translation is performed by Gettext.dgettext/3 with the domain "routes". Therefore for each configured locale, a "routes.pot" file is required containing the path segment translations for that locale.

Using the example Cldr backend that has "en" and "fr" Gettext locales then the directory structure would look like the following (if the default Gettext configuration is used):

priv/gettext
 default.pot
 en
    LC_MESSAGES
        default.po
        errors.po
        routes.po
 errors.pot
 fr
     LC_MESSAGES
         default.po
         errors.po
         routes.po

Summary

Functions

Generates localised routes for each locale defined in a Cldr backend.

Generates localised routes for each locale provided.

Functions

Link to this function

interpolate(path, locale)

View Source
Link to this macro

localize(list)

View Source (macro)

Generates localised routes for each locale defined in a Cldr backend.

This macro is intended to wrap a series of standard route definitiosn in a do block. For example:

localize do
  get "/pages/:page", PageController, :show
  resources "/users", UsersController
end
Link to this macro

localize(cldr_locale_names, arg2)

View Source (macro)

Generates localised routes for each locale provided.

This macro is intended to wrap a series of standard route definitiosn in a do block. For example:

localize [:en, :fr] do
  get "/pages/:page", PageController, :show
  resources "/users", UsersController
end
Link to this function

translate_path_now(path, gettext_backend, locale)

View Source