Skip to content

Commit

Permalink
Merge pull request #16 from elephantoss/i18n
Browse files Browse the repository at this point in the history
feat: add i18n support for default error messages
  • Loading branch information
srcrip authored Oct 7, 2024
2 parents d95a364 + 8b33d16 commit eaaf459
Show file tree
Hide file tree
Showing 15 changed files with 109 additions and 14 deletions.
37 changes: 36 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -152,14 +152,49 @@ You can change which corner the toasts are anchored to by passing the `corner` s
<LiveToast.toast_group flash={@flash} connected={assigns[:socket] != nil} corner={:top_right} />
```

### Internationalization

You can provide translations for the defaul error toasts by adding the following to your `config.exs`:

```elixir
config :live_toast,
gettext_backend: MyApp.Gettext
```

You have to create a `live_toast.po` file, inside the `priv/gettext/<language>/LC_MESSAGES/` folder for each language you want to support.

For example, if you want to support spanish, you would create the file `live_toast.po` in the `priv/gettext/es/LC_MESSAGES/` folder, with the following content:

```po
msgid ""
msgstr ""
"Language: es\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
msgid "We can't find the internet"
msgstr "Nosotros no podemos encontrar internet"
msgid "Attempting to reconnect"
msgstr "Intentando reconectar"
msgid "Something went wrong!"
msgstr "¡Algo salió mal!"
msgid "Hang in there while we get back on track"
msgstr "Aguanta mientras volvemos a la normalidad"
```

### Function Options

[`send_toast`](https://hexdocs.pm/live_toast/LiveToast.html#send_toast/3) takes a number of arguments to control it's behavior. They are currently:

- `kind`: The 'level' of this toast. The `component` function can receive this and modify behavior based on severity.
the `toast_class_fn` also receives it, and it can be used there to modify styles, for example, making `:info` toasts
green and `:error` toasts red.
- `body`: The primary text of the message.
- `body`: The primary text of the message.
- `title`: The optional title of the toast displayed at the top.
- `icon`: An optional function component that renders next to the title. You can use this with the default toast to display an icon.
- `action`: An optional function component that renders to the side. You can use this with the default toast to display an action, like a button.
Expand Down
3 changes: 3 additions & 0 deletions config/config.exs
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,6 @@ if Mix.env() == :dev do
~w(--format=iife --target=es2016 --global-name=LiveMotion --minify --outfile=../priv/static/live_toast.min.js)
)
end

config :live_toast,
gettext_backend: LiveToast.Gettext
3 changes: 3 additions & 0 deletions demo/config/config.exs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ config :demo, DemoWeb.Endpoint,
pubsub_server: Demo.PubSub,
live_view: [signing_salt: "mca0adK+"]

config :live_toast,
gettext_backend: Demo.Gettext

config :logger, :console,
format: "$time $metadata[$level] $message\n",
metadata: [:request_id]
Expand Down
4 changes: 4 additions & 0 deletions demo/lib/demo/gettext.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
defmodule Demo.Gettext do
@moduledoc false
use Gettext, otp_app: :demo
end
6 changes: 5 additions & 1 deletion demo/lib/demo_web/live/home_live.ex
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,11 @@ defmodule DemoWeb.HomeLive do
"action" => nil
}

def handle_params(_params, _uri, socket) do
def handle_params(params, _uri, socket) do
params
|> Map.get("locale", "en")
|> Gettext.put_locale()

socket =
socket
|> assign(:settings, @default_settings)
Expand Down
1 change: 1 addition & 0 deletions demo/mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ defmodule Demo.MixProject do
{:dialyxir, ">= 0.0.0", only: [:dev], runtime: false},
{:doctor, ">= 0.0.0", only: [:dev], runtime: false},
{:ex_doc, ">= 0.0.0", only: [:dev], runtime: false},
{:gettext, "~> 0.24"},
{:mix_audit, ">= 0.0.0", only: [:dev], runtime: false},
{:styler, "~> 0.11.9", only: [:dev, :test], runtime: false},
{:phoenix_html, "~> 4.0"},
Expand Down
2 changes: 2 additions & 0 deletions demo/mix.lock
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,10 @@
"esbuild": {:hex, :esbuild, "0.8.1", "0cbf919f0eccb136d2eeef0df49c4acf55336de864e63594adcea3814f3edf41", [:mix], [{:castore, ">= 0.0.0", [hex: :castore, repo: "hexpm", optional: false]}, {:jason, "~> 1.4", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "25fc876a67c13cb0a776e7b5d7974851556baeda2085296c14ab48555ea7560f"},
"ex_check": {:hex, :ex_check, "0.14.0", "d6fbe0bcc51cf38fea276f5bc2af0c9ae0a2bb059f602f8de88709421dae4f0e", [:mix], [], "hexpm", "8a602e98c66e6a4be3a639321f1f545292042f290f91fa942a285888c6868af0"},
"ex_doc": {:hex, :ex_doc, "0.32.2", "f60bbeb6ccbe75d005763e2a328e6f05e0624232f2393bc693611c2d3ae9fa0e", [:mix], [{:earmark_parser, "~> 1.4.39", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_c, ">= 0.1.0", [hex: :makeup_c, repo: "hexpm", optional: true]}, {:makeup_elixir, "~> 0.14 or ~> 1.0", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1 or ~> 1.0", [hex: :makeup_erlang, repo: "hexpm", optional: false]}, {:makeup_html, ">= 0.1.0", [hex: :makeup_html, repo: "hexpm", optional: true]}], "hexpm", "a4480305cdfe7fdfcbb77d1092c76161626d9a7aa4fb698aee745996e34602df"},
"expo": {:hex, :expo, "0.5.2", "beba786aab8e3c5431813d7a44b828e7b922bfa431d6bfbada0904535342efe2", [:mix], [], "hexpm", "8c9bfa06ca017c9cb4020fabe980bc7fdb1aaec059fd004c2ab3bff03b1c599c"},
"file_system": {:hex, :file_system, "1.0.0", "b689cc7dcee665f774de94b5a832e578bd7963c8e637ef940cd44327db7de2cd", [:mix], [], "hexpm", "6752092d66aec5a10e662aefeed8ddb9531d79db0bc145bb8c40325ca1d8536d"},
"floki": {:hex, :floki, "0.36.2", "a7da0193538c93f937714a6704369711998a51a6164a222d710ebd54020aa7a3", [:mix], [], "hexpm", "a8766c0bc92f074e5cb36c4f9961982eda84c5d2b8e979ca67f5c268ec8ed580"},
"gettext": {:hex, :gettext, "0.24.0", "6f4d90ac5f3111673cbefc4ebee96fe5f37a114861ab8c7b7d5b30a1108ce6d8", [:mix], [{:expo, "~> 0.5.1", [hex: :expo, repo: "hexpm", optional: false]}], "hexpm", "bdf75cdfcbe9e4622dd18e034b227d77dd17f0f133853a1c73b97b3d6c770e8b"},
"hpax": {:hex, :hpax, "0.1.2", "09a75600d9d8bbd064cdd741f21fc06fc1f4cf3d0fcc335e5aa19be1a7235c84", [:mix], [], "hexpm", "2c87843d5a23f5f16748ebe77969880e29809580efdaccd615cd3bed628a8c13"},
"jason": {:hex, :jason, "1.4.1", "af1504e35f629ddcdd6addb3513c3853991f694921b1b9368b0bd32beb9f1b63", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "fbb01ecdfd565b56261302f7e1fcc27c4fb8f32d56eab74db621fc154604a7a1"},
"makeup": {:hex, :makeup, "1.1.2", "9ba8837913bdf757787e71c1581c21f9d2455f4dd04cfca785c70bbfff1a76a3", [:mix], [{:nimble_parsec, "~> 1.2.2 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "cce1566b81fbcbd21eca8ffe808f33b221f9eee2cbc7a1706fc3da9ff18e6cac"},
Expand Down
19 changes: 19 additions & 0 deletions demo/priv/gettext/es/LC_MESSAGES/live_toast.po
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
msgid ""
msgstr ""
"Language: es\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"

msgid "We can't find the internet"
msgstr "Nosotros no podemos encontrar internet"

msgid "Attempting to reconnect"
msgstr "Intentando reconectar"

msgid "Something went wrong!"
msgstr "¡Algo salió mal!"

msgid "Hang in there while we get back on track"
msgstr "Aguanta mientras volvemos a la normalidad"
16 changes: 16 additions & 0 deletions demo/test/demo_web/live/home_live_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,22 @@ defmodule DemoWeb.HomeLiveTest do
end
end

describe "Localized demo page" do
test "renders error toasts in English", %{conn: conn} do
assert conn
|> get(~p"/")
|> html_response(200) =~
"We can&#39;t find the internet"
end

test "renders error toasts in Spanish", %{conn: conn} do
assert conn
|> get(~p"/?locale=es")
|> html_response(200) =~
"Nosotros no podemos encontrar internet"
end
end

describe "LiveToast.send_toast/7" do
test "renders correctly", %{conn: conn} do
{:ok, view, html} = live(conn, ~p"/")
Expand Down
8 changes: 4 additions & 4 deletions lib/live_toast/components.ex
Original file line number Diff line number Diff line change
Expand Up @@ -142,13 +142,13 @@ defmodule LiveToast.Components do
toast_class_fn={@toast_class_fn}
id="client-error"
kind={:error}
title="We can't find the internet"
title={Utility.translate("We can't find the internet")}
phx-update="ignore"
phx-disconnected={Utility.show(".phx-client-error #client-error")}
phx-connected={Utility.hide("#client-error")}
hidden
>
Attempting to reconnect
<%= Utility.translate("Attempting to reconnect") %>
<Utility.svg name="hero-arrow-path" class="inline-block ml-1 h-3 w-3 animate-spin" />
</.toast>
Expand All @@ -158,13 +158,13 @@ defmodule LiveToast.Components do
toast_class_fn={@toast_class_fn}
id="server-error"
kind={:error}
title="Something went wrong!"
title={Utility.translate("Something went wrong!")}
phx-update="ignore"
phx-disconnected={Utility.show(".phx-server-error #server-error")}
phx-connected={Utility.hide("#server-error")}
hidden
>
Hang in there while we get back on track
<%= Utility.translate("Hang in there while we get back on track") %>
<Utility.svg name="hero-arrow-path" class="inline-block ml-1 h-3 w-3 animate-spin" />
</.toast>
"""
Expand Down
4 changes: 4 additions & 0 deletions lib/live_toast/gettext.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
defmodule LiveToast.Gettext do
@moduledoc false
use Gettext, otp_app: :live_toast
end
11 changes: 3 additions & 8 deletions lib/live_toast/live_component.ex
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ defmodule LiveToast.LiveComponent do
use Phoenix.LiveComponent

alias LiveToast.Components
alias LiveToast.Utility

@impl Phoenix.LiveComponent
def mount(socket) do
Expand Down Expand Up @@ -61,16 +62,10 @@ defmodule LiveToast.LiveComponent do
icon={icon}
action={action}
corner={@corner}
title={
if title do
title
else
nil
end
}
title={if title, do: Utility.translate(title), else: nil}
target={@myself}
>
<%= body %>
<%= Utility.translate(body) %>
</Components.toast>
</div>
Expand Down
6 changes: 6 additions & 0 deletions lib/live_toast/utility.ex
Original file line number Diff line number Diff line change
Expand Up @@ -65,4 +65,10 @@ defmodule LiveToast.Utility do
"opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"}
)
end

def translate(message) do
:live_toast
|> Application.get_env(:gettext_backend, LiveToast.Gettext)
|> Gettext.dgettext("live_toast", message)
end
end
1 change: 1 addition & 0 deletions mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ defmodule LiveToast.MixProject do
{:dialyxir, ">= 0.0.0", only: [:dev], runtime: false},
{:doctor, ">= 0.0.0", only: [:dev], runtime: false},
{:ex_doc, "~> 0.32.2", only: [:dev], runtime: false},
{:gettext, "~> 0.24.0"},
{:mix_audit, ">= 0.0.0", only: [:dev], runtime: false},
{:styler, "~> 0.11.9", only: [:dev, :test], runtime: false},
{:makeup, "1.1.2", only: [:dev], runtime: false},
Expand Down
2 changes: 2 additions & 0 deletions mix.lock
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@
"esbuild": {:hex, :esbuild, "0.8.1", "0cbf919f0eccb136d2eeef0df49c4acf55336de864e63594adcea3814f3edf41", [:mix], [{:castore, ">= 0.0.0", [hex: :castore, repo: "hexpm", optional: false]}, {:jason, "~> 1.4", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "25fc876a67c13cb0a776e7b5d7974851556baeda2085296c14ab48555ea7560f"},
"ex_check": {:hex, :ex_check, "0.14.0", "d6fbe0bcc51cf38fea276f5bc2af0c9ae0a2bb059f602f8de88709421dae4f0e", [:mix], [], "hexpm", "8a602e98c66e6a4be3a639321f1f545292042f290f91fa942a285888c6868af0"},
"ex_doc": {:hex, :ex_doc, "0.32.2", "f60bbeb6ccbe75d005763e2a328e6f05e0624232f2393bc693611c2d3ae9fa0e", [:mix], [{:earmark_parser, "~> 1.4.39", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_c, ">= 0.1.0", [hex: :makeup_c, repo: "hexpm", optional: true]}, {:makeup_elixir, "~> 0.14 or ~> 1.0", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1 or ~> 1.0", [hex: :makeup_erlang, repo: "hexpm", optional: false]}, {:makeup_html, ">= 0.1.0", [hex: :makeup_html, repo: "hexpm", optional: true]}], "hexpm", "a4480305cdfe7fdfcbb77d1092c76161626d9a7aa4fb698aee745996e34602df"},
"expo": {:hex, :expo, "0.5.2", "beba786aab8e3c5431813d7a44b828e7b922bfa431d6bfbada0904535342efe2", [:mix], [], "hexpm", "8c9bfa06ca017c9cb4020fabe980bc7fdb1aaec059fd004c2ab3bff03b1c599c"},
"file_system": {:hex, :file_system, "1.0.0", "b689cc7dcee665f774de94b5a832e578bd7963c8e637ef940cd44327db7de2cd", [:mix], [], "hexpm", "6752092d66aec5a10e662aefeed8ddb9531d79db0bc145bb8c40325ca1d8536d"},
"gettext": {:hex, :gettext, "0.24.0", "6f4d90ac5f3111673cbefc4ebee96fe5f37a114861ab8c7b7d5b30a1108ce6d8", [:mix], [{:expo, "~> 0.5.1", [hex: :expo, repo: "hexpm", optional: false]}], "hexpm", "bdf75cdfcbe9e4622dd18e034b227d77dd17f0f133853a1c73b97b3d6c770e8b"},
"hpax": {:hex, :hpax, "0.1.2", "09a75600d9d8bbd064cdd741f21fc06fc1f4cf3d0fcc335e5aa19be1a7235c84", [:mix], [], "hexpm", "2c87843d5a23f5f16748ebe77969880e29809580efdaccd615cd3bed628a8c13"},
"jason": {:hex, :jason, "1.4.1", "af1504e35f629ddcdd6addb3513c3853991f694921b1b9368b0bd32beb9f1b63", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "fbb01ecdfd565b56261302f7e1fcc27c4fb8f32d56eab74db621fc154604a7a1"},
"makeup": {:hex, :makeup, "1.1.2", "9ba8837913bdf757787e71c1581c21f9d2455f4dd04cfca785c70bbfff1a76a3", [:mix], [{:nimble_parsec, "~> 1.2.2 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "cce1566b81fbcbd21eca8ffe808f33b221f9eee2cbc7a1706fc3da9ff18e6cac"},
Expand Down

0 comments on commit eaaf459

Please sign in to comment.