diff --git a/README.md b/README.md
index 9d1bc38f..a9d639f3 100644
--- a/README.md
+++ b/README.md
@@ -52,6 +52,7 @@ You can use the following environment variables to configure Cannery in
- `SECRET_KEY_BASE`: Secret key base used to sign cookies. Must be generated
with `docker exec -it cannery mix phx.gen.secret` and set for server to start.
- `REGISTRATION`: Controls if user sign-up should be invite only or set to public. Set to `public` to enable public registration. Defaults to `invite`.
+- `LOCALE`: Sets a custom locale. Defaults to `en_US`.
# Contribution
diff --git a/config/config.exs b/config/config.exs
index bb9c89d1..3083f460 100644
--- a/config/config.exs
+++ b/config/config.exs
@@ -40,6 +40,9 @@ config :cannery, Cannery.Mailer, adapter: Swoosh.Adapters.Local
# Swoosh API client is needed for adapters other than SMTP.
config :swoosh, :api_client, false
+# Gettext
+config :gettext, :default_locale, "en_US"
+
# Configure esbuild (the version is required)
# config :esbuild,
# version: "0.14.0",
diff --git a/config/runtime.exs b/config/runtime.exs
index 798ee937..6d2eaf18 100644
--- a/config/runtime.exs
+++ b/config/runtime.exs
@@ -12,6 +12,9 @@ if System.get_env("PHX_SERVER") && System.get_env("RELEASE_NAME") do
config :cannery, CanneryWeb.Endpoint, server: true
end
+# Set locale
+Gettext.put_locale(System.get_env("LOCALE") || "en_US")
+
maybe_ipv6 = if System.get_env("ECTO_IPV6"), do: [:inet6], else: []
database_url =
diff --git a/lib/cannery_web/views/error_helpers.ex b/lib/cannery_web/views/error_helpers.ex
index 6fce0636..ce054c20 100644
--- a/lib/cannery_web/views/error_helpers.ex
+++ b/lib/cannery_web/views/error_helpers.ex
@@ -17,12 +17,11 @@ defmodule CanneryWeb.ErrorHelpers do
assigns = %{extra_class: extra_class, form: form, field: field}
~H"""
- <%= for error <- Keyword.get_values(@form.errors, @field) do %>
-
- <%= translate_error(error) %>
-
- <% end %>
+ <%= for error <- Keyword.get_values(@form.errors, @field) do %>
+
+ <%= translate_error(error) %>
+
+ <% end %>
"""
end
@@ -61,9 +60,18 @@ defmodule CanneryWeb.ErrorHelpers do
@spec changeset_errors(Changeset.t()) :: String.t()
def changeset_errors(changeset) do
changeset
- |> Changeset.traverse_errors(fn error -> error |> translate_error() end)
+ |> changeset_error_map()
|> Enum.map_join(". ", fn {key, errors} ->
"#{key |> humanize()}: #{errors |> Enum.join(", ")}"
end)
end
+
+ @doc """
+ Displays all errors from a changeset in a key value map
+ """
+ @spec changeset_error_map(Changeset.t()) :: %{atom() => [String.t()]}
+ def changeset_error_map(changeset) do
+ changeset
+ |> Changeset.traverse_errors(fn error -> error |> translate_error() end)
+ end
end
diff --git a/mix.exs b/mix.exs
index 04f23b05..3a4995e0 100644
--- a/mix.exs
+++ b/mix.exs
@@ -69,7 +69,7 @@ defmodule Cannery.MixProject do
setup: ["deps.get", "compile", "ecto.setup", "cmd npm install --prefix assets"],
"ecto.setup": ["ecto.create", "ecto.migrate", "run priv/repo/seeds.exs"],
"ecto.reset": ["ecto.drop", "ecto.setup"],
- format: ["cmd npm run format --prefix assets", "format"],
+ format: ["cmd npm run format --prefix assets", "format", "gettext.extract"],
test: [
"cmd npm run test --prefix assets",
"dialyzer",