# Usage ## Installation You can install this library by adding it to your list of dependencies in `mix.exs`: ```elixir def deps do [ {:phoenix_localized_routes, "~> 0.1.0"} ] end ``` We pressed on making the installation as non-intrusive as possible; yet a few files have to be modified or created. ## Helpers `Phoenix Localized Routes` adds localization to the helpers created by Phoenix; no code changes in controllers and (live)views necessary. ```elixir # file: lib/example_web/example_web.ex # in controller - alias ExampleWeb.Router.Helpers, as: Routes + unquote(loc_helpers()) # in live_view + on_mount(ExampleWeb.LocalizedRoutes.LiveHelpers) # in router + import PhxLocalizedRoutes.Router + use PhxLocalizedRoutes.Router # in view_helpers - alias ExampleWeb.Router.Helpers, as: Routes + unquote(loc_helpers()) # insert new private function + defp loc_helpers do + quote do + import PhxLocalizedRoutes.Helpers + alias ExampleWeb.Router.Helpers, as: OriginalRoutes + alias ExampleWeb.Router.Helpers.Localized, as: Routes + alias ExampleWeb.LocalizedRoutes, as: Loc + end + end ``` ```elixir # file: lib/example_web/router.ex # Add to browser pipeline + plug(PhxLocalizedRoutes.Plug) ``` ## Configuration Create the module `[MyAppWeb].LocalizedRoutes` in the directory of your web application. The example shows a nested configuration using the default `[MyAppWeb].Gettext` module for multilingual URL's. It is possible to set: * `:scopes` - scopes as map of maps, the keys are used as URL segments (slugs). * `:gettext_module` - `Gettext` module to extract URL segments and translate them. For each local scope you can set. * `:assign` - a `Map` or `Struct` of values to assign to the `Plug.Conn` and/or `Phoenix.Socket`. When using a `Map` nested scopes inherit assigns from their parent. * `:scopes` - nested scopes Assigns are namespaced with `:loc`. They can be accessed in templates as `@loc.{key_name}` (e.g. `@loc.contact`) > #### Note {: .info} > > - using a `Struct` for `:assign`'s improves the developer experience. > - when using a `Struct` for assigns it should not be nested in the configuration module; but it can be in the same file as shown in the example. > - when a `Gettext` module is provided, the assigns must include a value for `:locale`. > > During compilation the configuration is validated. ```elixir # file /lib/example_web/localized_routes.ex # This example uses a `Struct` for assign, so there is no assign inheritance only struct defaults. When # using maps, nested scopes will inherit key/values from their parent. defmodule ExampleWeb.LocalizedRoutes.Assigns do @moduledoc false defstruct [:contact, locale: "en"] end defmodule ExampleWeb.LocalizedRoutes do alias Exampleeb.LocalizedRoutes.Assigns use PhxLocalizedRoutes, scopes: %{ "/" => %{ assign: %Assigns{contact: "root@example.com"}, scopes: %{ "/europe" => %{ assign: %Assigns{contact: "europe@example.com"}, scopes: %{ "/nl" => %{assigns: %Assigns{locale: "nl", contact: "verkoop@example.nl"}}, "/be" => %{assigns: %Assigns{locale: "nl", contact: "handel@example.be"}} } }, "/gb" => %{assign: %Assigns{contact: "sales@example.com"} } }, gettext_module: ExampleWeb.Gettext end ``` > #### Note {: .info} > > Your visitors may prefer another locale than the one set for the route they landed on. Libraries > like [Cldr.Plug.SetLocale](https://hexdocs.pm/ex_cldr/Cldr.Plug.SetLocale.html) can detect their preferences. > You can combine the value set by the route and the value set by a third party library to detect mismatches > and guide your visitors accordingly. ## Wrapping routes Wrap the routes within the scope in an `localized` block, providing your created `LocalizedRoutes` module as argument. ```elixir # file: router.ex scope "/", ExampleWeb do + localize ExampleWeb.LocalizedRoutes do [...routes] + end end ``` ## Extract translatable segments into `routes.po` files - Run `mix gettext.merge priv/gettext --locale [lang]}` to create a locales' folder - Run `mix gettext.extract --merge` after you updated routes. Now, we have created new routes PO file in our structure: web_app/priv/gettext └─ nl | └─ LC_MESSAGES | | └─ default.po | | └─ errors.po | | └─ routes.po <---- new! └─ en | └─ LC_MESSAGES | | └─ default.po | | └─ errors.po | | └─ routes.po <---- new! └─ default.pot └─ errors.pot └─ routes.pot <---- new! You can translate the route segments in the `.po`-file and recompile the Router module to generate the new multilingual routes. Finally, Phoenix Localized Routes is able to recompile routes whenever PO files change. To enable this feature, the :gettext compiler needs to be added to the list of Mix compilers. In mix.exs: ```elixir def project do [ compilers: [:gettext] ++ Mix.compilers, ] end ```