diff --git a/README.md b/README.md
index 484686a..cd9876f 100644
--- a/README.md
+++ b/README.md
@@ -152,6 +152,41 @@ You can change which corner the toasts are anchored to by passing the `corner` s
```
+### 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//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:
@@ -159,7 +194,7 @@ You can change which corner the toasts are anchored to by passing the `corner` s
- `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.
diff --git a/config/config.exs b/config/config.exs
index 65e81ec..2103d99 100644
--- a/config/config.exs
+++ b/config/config.exs
@@ -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
diff --git a/demo/config/config.exs b/demo/config/config.exs
index d1146fa..92ae11b 100644
--- a/demo/config/config.exs
+++ b/demo/config/config.exs
@@ -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]
diff --git a/demo/lib/demo/gettext.ex b/demo/lib/demo/gettext.ex
new file mode 100644
index 0000000..dff3c83
--- /dev/null
+++ b/demo/lib/demo/gettext.ex
@@ -0,0 +1,4 @@
+defmodule Demo.Gettext do
+ @moduledoc false
+ use Gettext, otp_app: :demo
+end
diff --git a/demo/lib/demo_web/live/home_live.ex b/demo/lib/demo_web/live/home_live.ex
index a873bee..525b98d 100644
--- a/demo/lib/demo_web/live/home_live.ex
+++ b/demo/lib/demo_web/live/home_live.ex
@@ -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)
diff --git a/demo/mix.exs b/demo/mix.exs
index 34749ec..c5304a0 100644
--- a/demo/mix.exs
+++ b/demo/mix.exs
@@ -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"},
diff --git a/demo/mix.lock b/demo/mix.lock
index a37ed4d..5239662 100644
--- a/demo/mix.lock
+++ b/demo/mix.lock
@@ -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"},
diff --git a/demo/priv/gettext/es/LC_MESSAGES/live_toast.po b/demo/priv/gettext/es/LC_MESSAGES/live_toast.po
new file mode 100644
index 0000000..db09862
--- /dev/null
+++ b/demo/priv/gettext/es/LC_MESSAGES/live_toast.po
@@ -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"
diff --git a/demo/test/demo_web/live/home_live_test.exs b/demo/test/demo_web/live/home_live_test.exs
index de7de93..1b7b595 100644
--- a/demo/test/demo_web/live/home_live_test.exs
+++ b/demo/test/demo_web/live/home_live_test.exs
@@ -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'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"/")
diff --git a/lib/live_toast/components.ex b/lib/live_toast/components.ex
index 0e2b537..90bfe68 100644
--- a/lib/live_toast/components.ex
+++ b/lib/live_toast/components.ex
@@ -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") %>
@@ -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") %>
"""
diff --git a/lib/live_toast/gettext.ex b/lib/live_toast/gettext.ex
new file mode 100644
index 0000000..e4dbfc6
--- /dev/null
+++ b/lib/live_toast/gettext.ex
@@ -0,0 +1,4 @@
+defmodule LiveToast.Gettext do
+ @moduledoc false
+ use Gettext, otp_app: :live_toast
+end
diff --git a/lib/live_toast/live_component.ex b/lib/live_toast/live_component.ex
index 805750b..882713d 100644
--- a/lib/live_toast/live_component.ex
+++ b/lib/live_toast/live_component.ex
@@ -4,6 +4,7 @@ defmodule LiveToast.LiveComponent do
use Phoenix.LiveComponent
alias LiveToast.Components
+ alias LiveToast.Utility
@impl Phoenix.LiveComponent
def mount(socket) do
@@ -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) %>
diff --git a/lib/live_toast/utility.ex b/lib/live_toast/utility.ex
index be704d0..5403943 100644
--- a/lib/live_toast/utility.ex
+++ b/lib/live_toast/utility.ex
@@ -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
diff --git a/mix.exs b/mix.exs
index 386e429..b024795 100644
--- a/mix.exs
+++ b/mix.exs
@@ -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},
diff --git a/mix.lock b/mix.lock
index 2eef446..24253d0 100644
--- a/mix.lock
+++ b/mix.lock
@@ -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"},