From c87334d31d1f2a6c43b9db019a3a85773f66f330 Mon Sep 17 00:00:00 2001 From: Graham McIntire Date: Fri, 24 Apr 2026 12:31:16 -0500 Subject: [PATCH] chore(deps): drop gettext MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit No translations are actually maintained and no UI is shipped in a non-English locale. Replaced the handful of gettext(...) calls in core_components + layouts with their literal English strings, and rewrote translate_error/1 as a small %{key} interpolator over the Ecto changeset error tuple. Removes gettext + expo (compile dep). sutra_ui stays — it's a transitive dep of live_table's TableComponent. --- config/dev.exs | 2 - lib/microwaveprop_web.ex | 4 - .../components/core_components.ex | 26 ++-- lib/microwaveprop_web/components/layouts.ex | 18 +-- lib/microwaveprop_web/gettext.ex | 25 ---- mix.exs | 4 +- mix.lock | 2 - priv/gettext/en/LC_MESSAGES/errors.po | 112 ------------------ priv/gettext/errors.pot | 109 ----------------- 9 files changed, 14 insertions(+), 288 deletions(-) delete mode 100644 lib/microwaveprop_web/gettext.ex delete mode 100644 priv/gettext/en/LC_MESSAGES/errors.po delete mode 100644 priv/gettext/errors.pot diff --git a/config/dev.exs b/config/dev.exs index 2c2bd08f..b1afcfa7 100644 --- a/config/dev.exs +++ b/config/dev.exs @@ -62,8 +62,6 @@ config :microwaveprop, MicrowavepropWeb.Endpoint, patterns: [ # Static assets, except user uploads ~r"priv/static/(?!uploads/).*\.(js|css|png|jpeg|jpg|gif|svg)$", - # Gettext translations - ~r"priv/gettext/.*\.po$", # Router, Controllers, LiveViews and LiveComponents ~r"lib/microwaveprop_web/router\.ex$", ~r"lib/microwaveprop_web/(controllers|live|components)/.*\.(ex|heex)$" diff --git a/lib/microwaveprop_web.ex b/lib/microwaveprop_web.ex index 34fa33e6..9144f4e8 100644 --- a/lib/microwaveprop_web.ex +++ b/lib/microwaveprop_web.ex @@ -40,7 +40,6 @@ defmodule MicrowavepropWeb do def controller do quote do use Phoenix.Controller, formats: [:html, :json] - use Gettext, backend: MicrowavepropWeb.Gettext import Plug.Conn @@ -81,9 +80,6 @@ defmodule MicrowavepropWeb do defp html_helpers do quote do - # Translation - use Gettext, backend: MicrowavepropWeb.Gettext - import MicrowavepropWeb.CoreComponents # HTML escaping functionality diff --git a/lib/microwaveprop_web/components/core_components.ex b/lib/microwaveprop_web/components/core_components.ex index 61dfa971..71fa2838 100644 --- a/lib/microwaveprop_web/components/core_components.ex +++ b/lib/microwaveprop_web/components/core_components.ex @@ -27,7 +27,6 @@ defmodule MicrowavepropWeb.CoreComponents do """ use Phoenix.Component - use Gettext, backend: MicrowavepropWeb.Gettext alias Phoenix.HTML.Form alias Phoenix.HTML.FormField @@ -73,7 +72,7 @@ defmodule MicrowavepropWeb.CoreComponents do

{msg}

-
@@ -397,7 +396,7 @@ defmodule MicrowavepropWeb.CoreComponents do {col[:label]} - {gettext("Actions")} + Actions @@ -504,24 +503,13 @@ defmodule MicrowavepropWeb.CoreComponents do end @doc """ - Translates an error message using gettext. + Interpolates an Ecto changeset error message. No i18n; plural messages + are left as-is (Ecto emits the appropriate form based on `:count`). """ def translate_error({msg, opts}) do - # When using gettext, we typically pass the strings we want - # to translate as a static argument: - # - # # Translate the number of files with plural rules - # dngettext("errors", "1 file", "%{count} files", count) - # - # However the error messages in our forms and APIs are generated - # dynamically, so we need to translate them by calling Gettext - # with our gettext backend as first argument. Translations are - # available in the errors.po file (as we use the "errors" domain). - if count = opts[:count] do - Gettext.dngettext(MicrowavepropWeb.Gettext, "errors", msg, msg, count, opts) - else - Gettext.dgettext(MicrowavepropWeb.Gettext, "errors", msg, opts) - end + Enum.reduce(opts, msg, fn {key, value}, acc -> + String.replace(acc, "%{#{key}}", fn _ -> to_string(value) end) + end) end @doc """ diff --git a/lib/microwaveprop_web/components/layouts.ex b/lib/microwaveprop_web/components/layouts.ex index caad3630..07021ccf 100644 --- a/lib/microwaveprop_web/components/layouts.ex +++ b/lib/microwaveprop_web/components/layouts.ex @@ -128,23 +128,13 @@ defmodule MicrowavepropWeb.Layouts do <.flash kind={:info} flash={@flash} /> <.flash kind={:error} flash={@flash} /> - <.flash - id="client-error" - kind={:error} - title={gettext("We can't find the internet")} - hidden - > - {gettext("Attempting to reconnect")} + <.flash id="client-error" kind={:error} title="We can't find the internet" hidden> + Attempting to reconnect <.icon name="hero-arrow-path" class="ml-1 size-3 motion-safe:animate-spin" /> - <.flash - id="server-error" - kind={:error} - title={gettext("Something went wrong!")} - hidden - > - {gettext("Attempting to reconnect")} + <.flash id="server-error" kind={:error} title="Something went wrong!" hidden> + Attempting to reconnect <.icon name="hero-arrow-path" class="ml-1 size-3 motion-safe:animate-spin" /> diff --git a/lib/microwaveprop_web/gettext.ex b/lib/microwaveprop_web/gettext.ex deleted file mode 100644 index c7dd4de2..00000000 --- a/lib/microwaveprop_web/gettext.ex +++ /dev/null @@ -1,25 +0,0 @@ -defmodule MicrowavepropWeb.Gettext do - @moduledoc """ - A module providing Internationalization with a gettext-based API. - - By using [Gettext](https://hexdocs.pm/gettext), your module compiles translations - that you can use in your application. To use this Gettext backend module, - call `use Gettext` and pass it as an option: - - use Gettext, backend: MicrowavepropWeb.Gettext - - # Simple translation - gettext("Here is the string to translate") - - # Plural translation - ngettext("Here is the string to translate", - "Here are the strings to translate", - 3) - - # Domain-based translation - dgettext("errors", "Here is the error message to translate") - - See the [Gettext Docs](https://hexdocs.pm/gettext) for detailed usage. - """ - use Gettext.Backend, otp_app: :microwaveprop -end diff --git a/mix.exs b/mix.exs index 6f25c959..84082d56 100644 --- a/mix.exs +++ b/mix.exs @@ -86,7 +86,6 @@ defmodule Microwaveprop.MixProject do {:opentelemetry_phoenix, "~> 2.0"}, {:opentelemetry_oban, "~> 1.1"}, {:opentelemetry_bandit, "~> 0.2"}, - {:gettext, "~> 0.26"}, {:jason, "~> 1.2"}, # Structured JSON log formatter plugged into Elixir 1.15+ :logger. # OTP 28 / Elixir 1.19 ships `Logger.Formatter.new/1` but no built-in @@ -110,6 +109,9 @@ defmodule Microwaveprop.MixProject do {:ecto_psql_extras, "~> 0.8"}, {:dialyxir, "~> 1.4", only: [:dev, :test], runtime: false}, {:live_table, "~> 0.4.1"}, + # Transitive dep of live_table (via LiveTable.TableComponent's + # generated code pulls in SutraUI.DropdownMenu). Pinned here + # because live_table doesn't list it in its own deps. {:sutra_ui, "~> 0.3.0"}, # Required as a compile-time build dependency for live_table; its mix # tasks (lib/mix/tasks/live_table.gen.live.ex, live_table.install.ex) diff --git a/mix.lock b/mix.lock index 23d76bfd..0e1ab1fb 100644 --- a/mix.lock +++ b/mix.lock @@ -22,12 +22,10 @@ "erlex": {:hex, :erlex, "0.2.8", "cd8116f20f3c0afe376d1e8d1f0ae2452337729f68be016ea544a72f767d9c12", [:mix], [], "hexpm", "9d66ff9fedf69e49dc3fd12831e12a8a37b76f8651dd21cd45fcf5561a8a7590"}, "esbuild": {:hex, :esbuild, "0.10.0", "b0aa3388a1c23e727c5a3e7427c932d89ee791746b0081bbe56103e9ef3d291f", [:mix], [{:jason, "~> 1.4", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "468489cda427b974a7cc9f03ace55368a83e1a7be12fba7e30969af78e5f8c70"}, "exla": {:hex, :exla, "0.11.0", "1428de9edcb297480a64611d3a72fcefe13c93c115bba6d38e910583c37e38c8", [:make, :mix], [{:elixir_make, "~> 0.6", [hex: :elixir_make, repo: "hexpm", optional: false]}, {:fine, "~> 0.1", [hex: :fine, repo: "hexpm", optional: false]}, {:nimble_pool, "~> 1.0", [hex: :nimble_pool, repo: "hexpm", optional: false]}, {:nx, "~> 0.11.0", [hex: :nx, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.0 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:xla, "~> 0.10.0", [hex: :xla, repo: "hexpm", optional: false]}], "hexpm", "1067207c802bd6f28cded6a2664979ee2e25dddce95cb84be3f0a3ebfbab2c74"}, - "expo": {:hex, :expo, "1.1.1", "4202e1d2ca6e2b3b63e02f69cfe0a404f77702b041d02b58597c00992b601db5", [:mix], [], "hexpm", "5fb308b9cb359ae200b7e23d37c76978673aa1b06e2b3075d814ce12c5811640"}, "file_system": {:hex, :file_system, "1.1.1", "31864f4685b0148f25bd3fbef2b1228457c0c89024ad67f7a81a3ffbc0bbad3a", [:mix], [], "hexpm", "7a15ff97dfe526aeefb090a7a9d3d03aa907e100e262a0f8f7746b78f8f87a5d"}, "finch": {:hex, :finch, "0.21.0", "b1c3b2d48af02d0c66d2a9ebfb5622be5c5ecd62937cf79a88a7f98d48a8290c", [:mix], [{:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:mint, "~> 1.6.2 or ~> 1.7", [hex: :mint, repo: "hexpm", optional: false]}, {:nimble_options, "~> 0.4 or ~> 1.0", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:nimble_pool, "~> 1.1", [hex: :nimble_pool, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "87dc6e169794cb2570f75841a19da99cfde834249568f2a5b121b809588a4377"}, "fine": {:hex, :fine, "0.1.6", "4bf7151493443c454aac9f2fa2f34f5fefd0346a83fb5586a016c4a135c63247", [:mix], [], "hexpm", "5638eb4495488e885ebec167fa57973e5c35e1a50c344eb7666c90ec1c4e3b12"}, "gen_smtp": {:hex, :gen_smtp, "1.3.0", "62c3d91f0dcf6ce9db71bcb6881d7ad0d1d834c7f38c13fa8e952f4104a8442e", [:rebar3], [{:ranch, ">= 1.8.0", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm", "0b73fbf069864ecbce02fe653b16d3f35fd889d0fdd4e14527675565c39d84e6"}, - "gettext": {:hex, :gettext, "0.26.2", "5978aa7b21fada6deabf1f6341ddba50bc69c999e812211903b169799208f2a8", [:mix], [{:expo, "~> 0.5.1 or ~> 1.0", [hex: :expo, repo: "hexpm", optional: false]}], "hexpm", "aa978504bcf76511efdc22d580ba08e2279caab1066b76bb9aa81c4a1e0a32a5"}, "glob_ex": {:hex, :glob_ex, "0.1.11", "cb50d3f1ef53f6ca04d6252c7fde09fd7a1cf63387714fe96f340a1349e62c93", [:mix], [], "hexpm", "342729363056e3145e61766b416769984c329e4378f1d558b63e341020525de4"}, "gproc": {:hex, :gproc, "0.9.1", "f1df0364423539cf0b80e8201c8b1839e229e5f9b3ccb944c5834626998f5b8c", [:rebar3], [], "hexpm", "905088e32e72127ed9466f0bac0d8e65704ca5e73ee5a62cb073c3117916d507"}, "grpcbox": {:hex, :grpcbox, "0.17.1", "6e040ab3ef16fe699ffb513b0ef8e2e896da7b18931a1ef817143037c454bcce", [:rebar3], [{:acceptor_pool, "~> 1.0.0", [hex: :acceptor_pool, repo: "hexpm", optional: false]}, {:chatterbox, "~> 0.15.1", [hex: :ts_chatterbox, repo: "hexpm", optional: false]}, {:ctx, "~> 0.6.0", [hex: :ctx, repo: "hexpm", optional: false]}, {:gproc, "~> 0.9.1", [hex: :gproc, repo: "hexpm", optional: false]}], "hexpm", "4a3b5d7111daabc569dc9cbd9b202a3237d81c80bf97212fbc676832cb0ceb17"}, diff --git a/priv/gettext/en/LC_MESSAGES/errors.po b/priv/gettext/en/LC_MESSAGES/errors.po deleted file mode 100644 index 844c4f5c..00000000 --- a/priv/gettext/en/LC_MESSAGES/errors.po +++ /dev/null @@ -1,112 +0,0 @@ -## `msgid`s in this file come from POT (.pot) files. -## -## Do not add, change, or remove `msgid`s manually here as -## they're tied to the ones in the corresponding POT file -## (with the same domain). -## -## Use `mix gettext.extract --merge` or `mix gettext.merge` -## to merge POT files into PO files. -msgid "" -msgstr "" -"Language: en\n" - -## From Ecto.Changeset.cast/4 -msgid "can't be blank" -msgstr "" - -## From Ecto.Changeset.unique_constraint/3 -msgid "has already been taken" -msgstr "" - -## From Ecto.Changeset.put_change/3 -msgid "is invalid" -msgstr "" - -## From Ecto.Changeset.validate_acceptance/3 -msgid "must be accepted" -msgstr "" - -## From Ecto.Changeset.validate_format/3 -msgid "has invalid format" -msgstr "" - -## From Ecto.Changeset.validate_subset/3 -msgid "has an invalid entry" -msgstr "" - -## From Ecto.Changeset.validate_exclusion/3 -msgid "is reserved" -msgstr "" - -## From Ecto.Changeset.validate_confirmation/3 -msgid "does not match confirmation" -msgstr "" - -## From Ecto.Changeset.no_assoc_constraint/3 -msgid "is still associated with this entry" -msgstr "" - -msgid "are still associated with this entry" -msgstr "" - -## From Ecto.Changeset.validate_length/3 -msgid "should have %{count} item(s)" -msgid_plural "should have %{count} item(s)" -msgstr[0] "" -msgstr[1] "" - -msgid "should be %{count} character(s)" -msgid_plural "should be %{count} character(s)" -msgstr[0] "" -msgstr[1] "" - -msgid "should be %{count} byte(s)" -msgid_plural "should be %{count} byte(s)" -msgstr[0] "" -msgstr[1] "" - -msgid "should have at least %{count} item(s)" -msgid_plural "should have at least %{count} item(s)" -msgstr[0] "" -msgstr[1] "" - -msgid "should be at least %{count} character(s)" -msgid_plural "should be at least %{count} character(s)" -msgstr[0] "" -msgstr[1] "" - -msgid "should be at least %{count} byte(s)" -msgid_plural "should be at least %{count} byte(s)" -msgstr[0] "" -msgstr[1] "" - -msgid "should have at most %{count} item(s)" -msgid_plural "should have at most %{count} item(s)" -msgstr[0] "" -msgstr[1] "" - -msgid "should be at most %{count} character(s)" -msgid_plural "should be at most %{count} character(s)" -msgstr[0] "" -msgstr[1] "" - -msgid "should be at most %{count} byte(s)" -msgid_plural "should be at most %{count} byte(s)" -msgstr[0] "" -msgstr[1] "" - -## From Ecto.Changeset.validate_number/3 -msgid "must be less than %{number}" -msgstr "" - -msgid "must be greater than %{number}" -msgstr "" - -msgid "must be less than or equal to %{number}" -msgstr "" - -msgid "must be greater than or equal to %{number}" -msgstr "" - -msgid "must be equal to %{number}" -msgstr "" diff --git a/priv/gettext/errors.pot b/priv/gettext/errors.pot deleted file mode 100644 index eef2de2b..00000000 --- a/priv/gettext/errors.pot +++ /dev/null @@ -1,109 +0,0 @@ -## This is a PO Template file. -## -## `msgid`s here are often extracted from source code. -## Add new translations manually only if they're dynamic -## translations that can't be statically extracted. -## -## Run `mix gettext.extract` to bring this file up to -## date. Leave `msgstr`s empty as changing them here has no -## effect: edit them in PO (`.po`) files instead. -## From Ecto.Changeset.cast/4 -msgid "can't be blank" -msgstr "" - -## From Ecto.Changeset.unique_constraint/3 -msgid "has already been taken" -msgstr "" - -## From Ecto.Changeset.put_change/3 -msgid "is invalid" -msgstr "" - -## From Ecto.Changeset.validate_acceptance/3 -msgid "must be accepted" -msgstr "" - -## From Ecto.Changeset.validate_format/3 -msgid "has invalid format" -msgstr "" - -## From Ecto.Changeset.validate_subset/3 -msgid "has an invalid entry" -msgstr "" - -## From Ecto.Changeset.validate_exclusion/3 -msgid "is reserved" -msgstr "" - -## From Ecto.Changeset.validate_confirmation/3 -msgid "does not match confirmation" -msgstr "" - -## From Ecto.Changeset.no_assoc_constraint/3 -msgid "is still associated with this entry" -msgstr "" - -msgid "are still associated with this entry" -msgstr "" - -## From Ecto.Changeset.validate_length/3 -msgid "should have %{count} item(s)" -msgid_plural "should have %{count} item(s)" -msgstr[0] "" -msgstr[1] "" - -msgid "should be %{count} character(s)" -msgid_plural "should be %{count} character(s)" -msgstr[0] "" -msgstr[1] "" - -msgid "should be %{count} byte(s)" -msgid_plural "should be %{count} byte(s)" -msgstr[0] "" -msgstr[1] "" - -msgid "should have at least %{count} item(s)" -msgid_plural "should have at least %{count} item(s)" -msgstr[0] "" -msgstr[1] "" - -msgid "should be at least %{count} character(s)" -msgid_plural "should be at least %{count} character(s)" -msgstr[0] "" -msgstr[1] "" - -msgid "should be at least %{count} byte(s)" -msgid_plural "should be at least %{count} byte(s)" -msgstr[0] "" -msgstr[1] "" - -msgid "should have at most %{count} item(s)" -msgid_plural "should have at most %{count} item(s)" -msgstr[0] "" -msgstr[1] "" - -msgid "should be at most %{count} character(s)" -msgid_plural "should be at most %{count} character(s)" -msgstr[0] "" -msgstr[1] "" - -msgid "should be at most %{count} byte(s)" -msgid_plural "should be at most %{count} byte(s)" -msgstr[0] "" -msgstr[1] "" - -## From Ecto.Changeset.validate_number/3 -msgid "must be less than %{number}" -msgstr "" - -msgid "must be greater than %{number}" -msgstr "" - -msgid "must be less than or equal to %{number}" -msgstr "" - -msgid "must be greater than or equal to %{number}" -msgstr "" - -msgid "must be equal to %{number}" -msgstr ""