feat: gettext

This commit is contained in:
Moritz 2025-06-17 19:02:35 +02:00
parent 2ab3332941
commit ca4ac3a1c0
Signed by: moritz
GPG key ID: 1020A035E5DD0824
15 changed files with 998 additions and 51 deletions

View file

@ -19,6 +19,10 @@ start-database:
ci-dev: lint audit test
gettext:
mix gettext.extract
mix gettext.merge priv/gettext
lint:
mix format --check-formatted
mix compile --warnings-as-errors

View file

@ -55,6 +55,7 @@ defmodule MvWeb do
use Phoenix.LiveView,
layout: {MvWeb.Layouts, :app}
on_mount MvWeb.LiveHelpers
unquote(html_helpers())
end
end

View file

@ -9,6 +9,13 @@
</p>
</div>
<div class="flex items-center gap-4 font-semibold leading-6 text-zinc-900">
<form method="post" action="/set_locale" class="mr-4">
<input type="hidden" name="_csrf_token" value={Plug.CSRFProtection.get_csrf_token()} />
<select name="locale" onchange="this.form.submit()" class="rounded border px-2 py-1">
<option value="de" selected={Gettext.get_locale() == "de"}>Deutsch</option>
<option value="en" selected={Gettext.get_locale() == "en"}>English</option>
</select>
</form>
<a href="https://twitter.com/elixirphoenix" class="hover:text-zinc-700">
@elixirphoenix
</a>

View file

@ -0,0 +1,9 @@
defmodule MvWeb.LiveHelpers do
import Phoenix.LiveView
def on_mount(:default, _params, session, socket) do
locale = session["locale"] || "en"
Gettext.put_locale(locale)
{:cont, socket}
end
end

View file

@ -0,0 +1,18 @@
defmodule MvWeb.LocaleController do
use MvWeb, :controller
def set_locale(conn, %{"locale" => locale}) do
conn
|> put_session(:locale, locale)
|> redirect(to: get_referer(conn) || "/")
end
defp get_referer(conn) do
conn.req_headers
|> Enum.find(fn {k, _v} -> k == "referer" end)
|> case do
{_, v} -> URI.parse(v).path
_ -> nil
end
end
end

View file

@ -26,7 +26,7 @@ defmodule MvWeb.MemberLive.FormComponent do
<div>
<.header>
{@title}
<:subtitle>Use this form to manage member records and their properties.</:subtitle>
<:subtitle>{gettext("Use this form to manage member records and their properties.")}</:subtitle>
</.header>
<.simple_form
@ -36,21 +36,21 @@ defmodule MvWeb.MemberLive.FormComponent do
phx-change="validate"
phx-submit="save"
>
<.input field={@form[:first_name]} label="First Name" required />
<.input field={@form[:last_name]} label="Last Name" required />
<.input field={@form[:email]} label="Email" required type="email" />
<.input field={@form[:birth_date]} label="Birth Date" type="date" />
<.input field={@form[:paid]} label="Paid" type="checkbox" />
<.input field={@form[:phone_number]} label="Phone Number" />
<.input field={@form[:join_date]} label="Join Date" type="date" />
<.input field={@form[:exit_date]} label="Exit Date" type="date" />
<.input field={@form[:notes]} label="Notes" />
<.input field={@form[:city]} label="City" />
<.input field={@form[:street]} label="Street" />
<.input field={@form[:house_number]} label="House Number" />
<.input field={@form[:postal_code]} label="Postal Code" />
<.input field={@form[:first_name]} label={gettext("First Name")} required />
<.input field={@form[:last_name]} label={gettext("Last Name")} required />
<.input field={@form[:email]} label={gettext("Email")} required type="email" />
<.input field={@form[:birth_date]} label={gettext("Birth Date")} type="date" />
<.input field={@form[:paid]} label={gettext("Paid")} type="checkbox" />
<.input field={@form[:phone_number]} label={gettext("Phone Number")} />
<.input field={@form[:join_date]} label={gettext("Join Date")} type="date" />
<.input field={@form[:exit_date]} label={gettext("Exit Date")} type="date" />
<.input field={@form[:notes]} label={gettext("Notes")} />
<.input field={@form[:city]} label={gettext("City")} />
<.input field={@form[:street]} label={gettext("Street")} />
<.input field={@form[:house_number]} label={gettext("House Number")} />
<.input field={@form[:postal_code]} label={gettext("Postal Code")} />
<h3 class="mt-8 mb-2 text-lg font-semibold">Custom Properties</h3>
<h3 class="mt-8 mb-2 text-lg font-semibold">{gettext("Custom Properties")}</h3>
<.inputs_for :let={f_property} field={@form[:properties]}>
<% type = Enum.find(@property_types, &(&1.id == f_property[:property_type_id].value)) %>
<.inputs_for :let={value_form} field={f_property[:value]}>
@ -70,7 +70,7 @@ defmodule MvWeb.MemberLive.FormComponent do
</.inputs_for>
<:actions>
<.button phx-disable-with="Saving...">Save Member</.button>
<.button phx-disable-with={gettext("Saving...")}>{gettext("Save Member")}</.button>
</:actions>
</.simple_form>
</div>
@ -95,9 +95,16 @@ defmodule MvWeb.MemberLive.FormComponent do
{:ok, member} ->
notify_parent({:saved, member})
action =
case socket.assigns.form.source.type do
:create -> gettext("create")
:update -> gettext("update")
other -> to_string(other)
end
socket =
socket
|> put_flash(:info, "Member #{socket.assigns.form.source.type}d successfully")
|> put_flash(:info, gettext("Mitglied %{action} erfolgreich", action: action))
|> push_patch(to: socket.assigns.patch)
{:noreply, socket}

View file

@ -5,10 +5,10 @@ defmodule MvWeb.MemberLive.Index do
def render(assigns) do
~H"""
<.header>
Listing Members
{gettext("Listing Members")}
<:actions>
<.link patch={~p"/members/new"}>
<.button>New Member</.button>
<.button>{gettext("New Member")}</.button>
</.link>
</:actions>
</.header>
@ -19,26 +19,26 @@ defmodule MvWeb.MemberLive.Index do
row_click={fn {_id, member} -> JS.navigate(~p"/members/#{member}") end}
>
<!-- <:col :let={{_id, member}} label="Id">{member.id}</:col> -->
<:col :let={{_id, member}} label="First Name">{member.first_name}</:col>
<:col :let={{_id, member}} label="Last Name">{member.last_name}</:col>
<:col :let={{_id, member}} label="Email">{member.email}</:col>
<:col :let={{_id, member}} label="City">{member.city}</:col>
<:col :let={{_id, member}} label="Join Date">{member.join_date}</:col>
<:col :let={{_id, member}} label={gettext("First Name")}>{member.first_name}</:col>
<:col :let={{_id, member}} label={gettext("Last Name")}>{member.last_name}</:col>
<:col :let={{_id, member}} label={gettext("Email")}>{member.email}</:col>
<:col :let={{_id, member}} label={gettext("City")}>{member.city}</:col>
<:col :let={{_id, member}} label={gettext("Join Date")}>{member.join_date}</:col>
<:action :let={{_id, member}}>
<div class="sr-only">
<.link navigate={~p"/members/#{member}"}>Show</.link>
<.link navigate={~p"/members/#{member}"}>{gettext("Show")}</.link>
</div>
<.link patch={~p"/members/#{member}/edit"}>Edit</.link>
<.link patch={~p"/members/#{member}/edit"}>{gettext("Edit")}</.link>
</:action>
<:action :let={{id, member}}>
<.link
phx-click={JS.push("delete", value: %{id: member.id}) |> hide("##{id}")}
data-confirm="Are you sure?"
data-confirm={gettext("Are you sure?")}
>
Delete
{gettext("Delete")}
</.link>
</:action>
</.table>
@ -73,19 +73,19 @@ defmodule MvWeb.MemberLive.Index do
defp apply_action(socket, :edit, %{"id" => id}) do
socket
|> assign(:page_title, "Edit Member")
|> assign(:page_title, gettext("Edit Member"))
|> assign(:member, Ash.get!(Mv.Membership.Member, id))
end
defp apply_action(socket, :new, _params) do
socket
|> assign(:page_title, "New Member")
|> assign(:page_title, gettext("New Member"))
|> assign(:member, nil)
end
defp apply_action(socket, :index, _params) do
socket
|> assign(:page_title, "Listing Members")
|> assign(:page_title, gettext("Listing Members"))
|> assign(:member, nil)
end

View file

@ -7,33 +7,33 @@ defmodule MvWeb.MemberLive.Show do
~H"""
<.header>
{@member.first_name} {@member.last_name}
<:subtitle>This is a member record from your database.</:subtitle>
<:subtitle>{gettext("This is a member record from your database.")}</:subtitle>
<:actions>
<.link patch={~p"/members/#{@member}/show/edit"} phx-click={JS.push_focus()}>
<.button>Edit member</.button>
<.button>{gettext("Edit member")}</.button>
</.link>
</:actions>
</.header>
<.list>
<:item title="Id">{@member.id}</:item>
<:item title="First Name">{@member.first_name}</:item>
<:item title="Last Name">{@member.last_name}</:item>
<:item title="Email">{@member.email}</:item>
<:item title="Birth Date">{@member.birth_date}</:item>
<:item title="Paid">{if @member.paid, do: "Yes", else: "No"}</:item>
<:item title="Phone Number">{@member.phone_number}</:item>
<:item title="Join Date">{@member.join_date}</:item>
<:item title="Exit Date">{@member.exit_date}</:item>
<:item title="Notes">{@member.notes}</:item>
<:item title="City">{@member.city}</:item>
<:item title="Street">{@member.street}</:item>
<:item title="House Number">{@member.house_number}</:item>
<:item title="Postal Code">{@member.postal_code}</:item>
<:item title={gettext("Id")}>{@member.id}</:item>
<:item title={gettext("First Name")}>{@member.first_name}</:item>
<:item title={gettext("Last Name")}>{@member.last_name}</:item>
<:item title={gettext("Email")}>{@member.email}</:item>
<:item title={gettext("Birth Date")}>{@member.birth_date}</:item>
<:item title={gettext("Paid")}>{if @member.paid, do: gettext("Yes"), else: gettext("No")}</:item>
<:item title={gettext("Phone Number")}>{@member.phone_number}</:item>
<:item title={gettext("Join Date")}>{@member.join_date}</:item>
<:item title={gettext("Exit Date")}>{@member.exit_date}</:item>
<:item title={gettext("Notes")}>{@member.notes}</:item>
<:item title={gettext("City")}>{@member.city}</:item>
<:item title={gettext("Street")}>{@member.street}</:item>
<:item title={gettext("House Number")}>{@member.house_number}</:item>
<:item title={gettext("Postal Code")}>{@member.postal_code}</:item>
</.list>
<h3 class="mt-8 mb-2 text-lg font-semibold">Custom Properties</h3>
<h3 class="mt-8 mb-2 text-lg font-semibold">{gettext("Custom Properties")}</h3>
<.generic_list items={
Enum.map(@member.properties, fn p ->
{
@ -47,7 +47,7 @@ defmodule MvWeb.MemberLive.Show do
}
end)
} />
<.back navigate={~p"/members"}>Back to members</.back>
<.back navigate={~p"/members"}>{gettext("Back to members")}</.back>
<.modal
:if={@live_action == :edit}
@ -87,6 +87,6 @@ defmodule MvWeb.MemberLive.Show do
|> assign(:member, member)}
end
defp page_title(:show), do: "Show Member"
defp page_title(:edit), do: "Edit Member"
defp page_title(:show), do: gettext("Show Member")
defp page_title(:edit), do: gettext("Edit Member")
end

View file

@ -8,6 +8,7 @@ defmodule MvWeb.Router do
plug :put_root_layout, html: {MvWeb.Layouts, :root}
plug :protect_from_forgery
plug :put_secure_browser_headers
plug :set_locale
end
pipeline :api do
@ -35,6 +36,8 @@ defmodule MvWeb.Router do
live "/properties/:id/edit", PropertyLive.Index, :edit
live "/properties/:id", PropertyLive.Show, :show
live "/properties/:id/show/edit", PropertyLive.Show, :edit
post "/set_locale", LocaleController, :set_locale
end
# Other scopes may use custom stacks.
@ -68,4 +71,10 @@ defmodule MvWeb.Router do
ash_admin "/"
end
end
defp set_locale(conn, _opts) do
locale = get_session(conn, :locale) || "en"
Gettext.put_locale(MvWeb.Gettext, locale)
conn
end
end

View file

@ -0,0 +1,244 @@
## `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"
#: lib/mv_web/components/core_components.ex:482
#, elixir-autogen, elixir-format
msgid "Actions"
msgstr ""
#: lib/mv_web/member_live/index.ex:39
#, elixir-autogen, elixir-format
msgid "Are you sure?"
msgstr "Bist du sicher?"
#: lib/mv_web/components/core_components.ex:160
#, elixir-autogen, elixir-format
msgid "Attempting to reconnect"
msgstr "Verbindung wird wiederhergestellt"
#: lib/mv_web/member_live/form_component.ex:48
#: lib/mv_web/member_live/index.ex:25
#: lib/mv_web/member_live/show.ex:30
#, elixir-autogen, elixir-format
msgid "City"
msgstr "Stadt"
#: lib/mv_web/member_live/index.ex:41
#, elixir-autogen, elixir-format
msgid "Delete"
msgstr "Löschen"
#: lib/mv_web/member_live/index.ex:33
#, elixir-autogen, elixir-format
msgid "Edit"
msgstr "Bearbeiten"
#: lib/mv_web/member_live/index.ex:76
#: lib/mv_web/member_live/show.ex:91
#, elixir-autogen, elixir-format
msgid "Edit Member"
msgstr "Mitglied bearbeiten"
#: lib/mv_web/member_live/form_component.ex:41
#: lib/mv_web/member_live/index.ex:24
#: lib/mv_web/member_live/show.ex:23
#, elixir-autogen, elixir-format
msgid "Email"
msgstr "E-Mail"
#: lib/mv_web/components/core_components.ex:151
#, elixir-autogen, elixir-format
msgid "Error!"
msgstr "Fehler!"
#: lib/mv_web/member_live/form_component.ex:39
#: lib/mv_web/member_live/index.ex:22
#: lib/mv_web/member_live/show.ex:21
#, elixir-autogen, elixir-format
msgid "First Name"
msgstr "Vorname"
#: lib/mv_web/components/core_components.ex:172
#, elixir-autogen, elixir-format
msgid "Hang in there while we get back on track"
msgstr "Bitte warten, wir stellen die Verbindung wieder her."
#: lib/mv_web/member_live/form_component.ex:45
#: lib/mv_web/member_live/index.ex:26
#: lib/mv_web/member_live/show.ex:27
#, elixir-autogen, elixir-format
msgid "Join Date"
msgstr "Beitrittsdatum"
#: lib/mv_web/member_live/form_component.ex:40
#: lib/mv_web/member_live/index.ex:23
#: lib/mv_web/member_live/show.ex:22
#, elixir-autogen, elixir-format
msgid "Last Name"
msgstr "Nachname"
#: lib/mv_web/member_live/index.ex:8
#: lib/mv_web/member_live/index.ex:88
#, elixir-autogen, elixir-format
msgid "Listing Members"
msgstr "Mitglieder"
#: lib/mv_web/member_live/index.ex:11
#: lib/mv_web/member_live/index.ex:82
#, elixir-autogen, elixir-format
msgid "New Member"
msgstr "Neues Mitglied"
#: lib/mv_web/member_live/index.ex:30
#, elixir-autogen, elixir-format
msgid "Show"
msgstr "Anzeigen"
#: lib/mv_web/components/core_components.ex:167
#, elixir-autogen, elixir-format
msgid "Something went wrong!"
msgstr "Etwas ist schiefgelaufen!"
#: lib/mv_web/components/core_components.ex:150
#, elixir-autogen, elixir-format
msgid "Success!"
msgstr "Erfolg!"
#: lib/mv_web/components/core_components.ex:155
#, elixir-autogen, elixir-format
msgid "We can't find the internet"
msgstr "Keine Internetverbindung gefunden"
#: lib/mv_web/components/core_components.ex:76
#: lib/mv_web/components/core_components.ex:130
#, elixir-autogen, elixir-format
msgid "close"
msgstr "schließen"
#: lib/mv_web/member_live/form_component.ex:42
#: lib/mv_web/member_live/show.ex:24
#, elixir-autogen, elixir-format
msgid "Birth Date"
msgstr "Geburtsdatum"
#: lib/mv_web/member_live/form_component.ex:53
#: lib/mv_web/member_live/show.ex:36
#, elixir-autogen, elixir-format
msgid "Custom Properties"
msgstr "Eigene Eigenschaften"
#: lib/mv_web/member_live/form_component.ex:46
#: lib/mv_web/member_live/show.ex:28
#, elixir-autogen, elixir-format
msgid "Exit Date"
msgstr "Austrittsdatum"
#: lib/mv_web/member_live/form_component.ex:50
#: lib/mv_web/member_live/show.ex:32
#, elixir-autogen, elixir-format
msgid "House Number"
msgstr "Hausnummer"
#: lib/mv_web/member_live/form_component.ex:47
#: lib/mv_web/member_live/show.ex:29
#, elixir-autogen, elixir-format
msgid "Notes"
msgstr "Notizen"
#: lib/mv_web/member_live/form_component.ex:43
#: lib/mv_web/member_live/show.ex:25
#, elixir-autogen, elixir-format
msgid "Paid"
msgstr "Bezahlt"
#: lib/mv_web/member_live/form_component.ex:44
#: lib/mv_web/member_live/show.ex:26
#, elixir-autogen, elixir-format
msgid "Phone Number"
msgstr "Telefonnummer"
#: lib/mv_web/member_live/form_component.ex:51
#: lib/mv_web/member_live/show.ex:33
#, elixir-autogen, elixir-format
msgid "Postal Code"
msgstr "Postleitzahl"
#: lib/mv_web/member_live/form_component.ex:73
#, elixir-autogen, elixir-format
msgid "Save Member"
msgstr "Mitglied speichern"
#: lib/mv_web/member_live/form_component.ex:73
#, elixir-autogen, elixir-format
msgid "Saving..."
msgstr "Speichern..."
#: lib/mv_web/member_live/form_component.ex:49
#: lib/mv_web/member_live/show.ex:31
#, elixir-autogen, elixir-format
msgid "Street"
msgstr "Straße"
#: lib/mv_web/member_live/form_component.ex:29
#, elixir-autogen, elixir-format
msgid "Use this form to manage member records and their properties."
msgstr "Dieses Formular dient zur Verwaltung von Mitgliedern und deren Eigenschaften."
#: lib/mv_web/member_live/show.ex:50
#, elixir-autogen, elixir-format
msgid "Back to members"
msgstr "Zurück zur Mitgliederliste"
#: lib/mv_web/member_live/show.ex:14
#, elixir-autogen, elixir-format
msgid "Edit member"
msgstr "Mitglied bearbeiten"
#: lib/mv_web/member_live/show.ex:20
#, elixir-autogen, elixir-format
msgid "Id"
msgstr "ID"
#: lib/mv_web/member_live/show.ex:25
#, elixir-autogen, elixir-format
msgid "No"
msgstr "Nein"
#: lib/mv_web/member_live/show.ex:90
#, elixir-autogen, elixir-format, fuzzy
msgid "Show Member"
msgstr "Mitglied anzeigen"
#: lib/mv_web/member_live/show.ex:10
#, elixir-autogen, elixir-format
msgid "This is a member record from your database."
msgstr "Dies ist ein Mitglied aus deiner Datenbank."
#: lib/mv_web/member_live/show.ex:25
#, elixir-autogen, elixir-format
msgid "Yes"
msgstr "Ja"
#: lib/mv_web/member_live/form_component.ex:107
#, elixir-autogen, elixir-format
msgid "Mitglied %{action} erfolgreich"
msgstr "Mitglied %{action} erfolgreich"
#: lib/mv_web/member_live/form_component.ex:100
#, elixir-autogen, elixir-format
msgid "create"
msgstr "erstellt"
#: lib/mv_web/member_live/form_component.ex:101
#, elixir-autogen, elixir-format
msgid "update"
msgstr "aktualisiert"

View file

@ -0,0 +1,133 @@
## `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 ""
msgid "is not a valid email"
msgstr "ist keine gültige E-Mail-Adresse"
msgid "cannot be in the future"
msgstr "darf nicht in der Zukunft liegen"
msgid "must be present"
msgstr "muss ausgefüllt sein"
msgid "is not a valid phone number"
msgstr "ist keine gültige Telefonnummer"
msgid "length must be greater than or equal to 5"
msgstr "Die Länge muss mindestens 5 Zeichen betragen"
msgid "cannot be before join date"
msgstr "darf nicht vor dem Eintrittsdatum liegen"
msgid "must consist of 5 digits"
msgstr "muss aus 5 Ziffern bestehen"

245
priv/gettext/default.pot Normal file
View file

@ -0,0 +1,245 @@
## This file is a PO Template file.
##
## "msgid"s here are often extracted from source code.
## Add new messages manually only if they're dynamic
## messages 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.
#
msgid ""
msgstr ""
#: lib/mv_web/components/core_components.ex:482
#, elixir-autogen, elixir-format
msgid "Actions"
msgstr ""
#: lib/mv_web/member_live/index.ex:39
#, elixir-autogen, elixir-format
msgid "Are you sure?"
msgstr ""
#: lib/mv_web/components/core_components.ex:160
#, elixir-autogen, elixir-format
msgid "Attempting to reconnect"
msgstr ""
#: lib/mv_web/member_live/form_component.ex:48
#: lib/mv_web/member_live/index.ex:25
#: lib/mv_web/member_live/show.ex:30
#, elixir-autogen, elixir-format
msgid "City"
msgstr ""
#: lib/mv_web/member_live/index.ex:41
#, elixir-autogen, elixir-format
msgid "Delete"
msgstr ""
#: lib/mv_web/member_live/index.ex:33
#, elixir-autogen, elixir-format
msgid "Edit"
msgstr ""
#: lib/mv_web/member_live/index.ex:76
#: lib/mv_web/member_live/show.ex:91
#, elixir-autogen, elixir-format
msgid "Edit Member"
msgstr ""
#: lib/mv_web/member_live/form_component.ex:41
#: lib/mv_web/member_live/index.ex:24
#: lib/mv_web/member_live/show.ex:23
#, elixir-autogen, elixir-format
msgid "Email"
msgstr ""
#: lib/mv_web/components/core_components.ex:151
#, elixir-autogen, elixir-format
msgid "Error!"
msgstr ""
#: lib/mv_web/member_live/form_component.ex:39
#: lib/mv_web/member_live/index.ex:22
#: lib/mv_web/member_live/show.ex:21
#, elixir-autogen, elixir-format
msgid "First Name"
msgstr ""
#: lib/mv_web/components/core_components.ex:172
#, elixir-autogen, elixir-format
msgid "Hang in there while we get back on track"
msgstr ""
#: lib/mv_web/member_live/form_component.ex:45
#: lib/mv_web/member_live/index.ex:26
#: lib/mv_web/member_live/show.ex:27
#, elixir-autogen, elixir-format
msgid "Join Date"
msgstr ""
#: lib/mv_web/member_live/form_component.ex:40
#: lib/mv_web/member_live/index.ex:23
#: lib/mv_web/member_live/show.ex:22
#, elixir-autogen, elixir-format
msgid "Last Name"
msgstr ""
#: lib/mv_web/member_live/index.ex:8
#: lib/mv_web/member_live/index.ex:88
#, elixir-autogen, elixir-format
msgid "Listing Members"
msgstr ""
#: lib/mv_web/member_live/index.ex:11
#: lib/mv_web/member_live/index.ex:82
#, elixir-autogen, elixir-format
msgid "New Member"
msgstr ""
#: lib/mv_web/member_live/index.ex:30
#, elixir-autogen, elixir-format
msgid "Show"
msgstr ""
#: lib/mv_web/components/core_components.ex:167
#, elixir-autogen, elixir-format
msgid "Something went wrong!"
msgstr ""
#: lib/mv_web/components/core_components.ex:150
#, elixir-autogen, elixir-format
msgid "Success!"
msgstr ""
#: lib/mv_web/components/core_components.ex:155
#, elixir-autogen, elixir-format
msgid "We can't find the internet"
msgstr ""
#: lib/mv_web/components/core_components.ex:76
#: lib/mv_web/components/core_components.ex:130
#, elixir-autogen, elixir-format
msgid "close"
msgstr ""
#: lib/mv_web/member_live/form_component.ex:42
#: lib/mv_web/member_live/show.ex:24
#, elixir-autogen, elixir-format
msgid "Birth Date"
msgstr ""
#: lib/mv_web/member_live/form_component.ex:53
#: lib/mv_web/member_live/show.ex:36
#, elixir-autogen, elixir-format
msgid "Custom Properties"
msgstr ""
#: lib/mv_web/member_live/form_component.ex:46
#: lib/mv_web/member_live/show.ex:28
#, elixir-autogen, elixir-format
msgid "Exit Date"
msgstr ""
#: lib/mv_web/member_live/form_component.ex:50
#: lib/mv_web/member_live/show.ex:32
#, elixir-autogen, elixir-format
msgid "House Number"
msgstr ""
#: lib/mv_web/member_live/form_component.ex:47
#: lib/mv_web/member_live/show.ex:29
#, elixir-autogen, elixir-format
msgid "Notes"
msgstr ""
#: lib/mv_web/member_live/form_component.ex:43
#: lib/mv_web/member_live/show.ex:25
#, elixir-autogen, elixir-format
msgid "Paid"
msgstr ""
#: lib/mv_web/member_live/form_component.ex:44
#: lib/mv_web/member_live/show.ex:26
#, elixir-autogen, elixir-format
msgid "Phone Number"
msgstr ""
#: lib/mv_web/member_live/form_component.ex:51
#: lib/mv_web/member_live/show.ex:33
#, elixir-autogen, elixir-format
msgid "Postal Code"
msgstr ""
#: lib/mv_web/member_live/form_component.ex:73
#, elixir-autogen, elixir-format
msgid "Save Member"
msgstr ""
#: lib/mv_web/member_live/form_component.ex:73
#, elixir-autogen, elixir-format
msgid "Saving..."
msgstr ""
#: lib/mv_web/member_live/form_component.ex:49
#: lib/mv_web/member_live/show.ex:31
#, elixir-autogen, elixir-format
msgid "Street"
msgstr ""
#: lib/mv_web/member_live/form_component.ex:29
#, elixir-autogen, elixir-format
msgid "Use this form to manage member records and their properties."
msgstr ""
#: lib/mv_web/member_live/show.ex:50
#, elixir-autogen, elixir-format
msgid "Back to members"
msgstr ""
#: lib/mv_web/member_live/show.ex:14
#, elixir-autogen, elixir-format
msgid "Edit member"
msgstr ""
#: lib/mv_web/member_live/show.ex:20
#, elixir-autogen, elixir-format
msgid "Id"
msgstr ""
#: lib/mv_web/member_live/show.ex:25
#, elixir-autogen, elixir-format
msgid "No"
msgstr ""
#: lib/mv_web/member_live/show.ex:90
#, elixir-autogen, elixir-format
msgid "Show Member"
msgstr ""
#: lib/mv_web/member_live/show.ex:10
#, elixir-autogen, elixir-format
msgid "This is a member record from your database."
msgstr ""
#: lib/mv_web/member_live/show.ex:25
#, elixir-autogen, elixir-format
msgid "Yes"
msgstr ""
#: lib/mv_web/member_live/form_component.ex:107
#, elixir-autogen, elixir-format
msgid "Mitglied %{action} erfolgreich"
msgstr ""
#: lib/mv_web/member_live/form_component.ex:100
#, elixir-autogen, elixir-format
msgid "create"
msgstr ""
#: lib/mv_web/member_live/form_component.ex:101
#, elixir-autogen, elixir-format
msgid "update"
msgstr ""

View file

@ -0,0 +1,245 @@
## "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"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: lib/mv_web/components/core_components.ex:482
#, elixir-autogen, elixir-format
msgid "Actions"
msgstr ""
#: lib/mv_web/member_live/index.ex:39
#, elixir-autogen, elixir-format
msgid "Are you sure?"
msgstr ""
#: lib/mv_web/components/core_components.ex:160
#, elixir-autogen, elixir-format
msgid "Attempting to reconnect"
msgstr ""
#: lib/mv_web/member_live/form_component.ex:48
#: lib/mv_web/member_live/index.ex:25
#: lib/mv_web/member_live/show.ex:30
#, elixir-autogen, elixir-format
msgid "City"
msgstr ""
#: lib/mv_web/member_live/index.ex:41
#, elixir-autogen, elixir-format
msgid "Delete"
msgstr ""
#: lib/mv_web/member_live/index.ex:33
#, elixir-autogen, elixir-format
msgid "Edit"
msgstr ""
#: lib/mv_web/member_live/index.ex:76
#: lib/mv_web/member_live/show.ex:91
#, elixir-autogen, elixir-format
msgid "Edit Member"
msgstr ""
#: lib/mv_web/member_live/form_component.ex:41
#: lib/mv_web/member_live/index.ex:24
#: lib/mv_web/member_live/show.ex:23
#, elixir-autogen, elixir-format
msgid "Email"
msgstr ""
#: lib/mv_web/components/core_components.ex:151
#, elixir-autogen, elixir-format
msgid "Error!"
msgstr ""
#: lib/mv_web/member_live/form_component.ex:39
#: lib/mv_web/member_live/index.ex:22
#: lib/mv_web/member_live/show.ex:21
#, elixir-autogen, elixir-format
msgid "First Name"
msgstr ""
#: lib/mv_web/components/core_components.ex:172
#, elixir-autogen, elixir-format
msgid "Hang in there while we get back on track"
msgstr ""
#: lib/mv_web/member_live/form_component.ex:45
#: lib/mv_web/member_live/index.ex:26
#: lib/mv_web/member_live/show.ex:27
#, elixir-autogen, elixir-format
msgid "Join Date"
msgstr ""
#: lib/mv_web/member_live/form_component.ex:40
#: lib/mv_web/member_live/index.ex:23
#: lib/mv_web/member_live/show.ex:22
#, elixir-autogen, elixir-format
msgid "Last Name"
msgstr ""
#: lib/mv_web/member_live/index.ex:8
#: lib/mv_web/member_live/index.ex:88
#, elixir-autogen, elixir-format
msgid "Listing Members"
msgstr ""
#: lib/mv_web/member_live/index.ex:11
#: lib/mv_web/member_live/index.ex:82
#, elixir-autogen, elixir-format
msgid "New Member"
msgstr ""
#: lib/mv_web/member_live/index.ex:30
#, elixir-autogen, elixir-format
msgid "Show"
msgstr ""
#: lib/mv_web/components/core_components.ex:167
#, elixir-autogen, elixir-format
msgid "Something went wrong!"
msgstr ""
#: lib/mv_web/components/core_components.ex:150
#, elixir-autogen, elixir-format
msgid "Success!"
msgstr ""
#: lib/mv_web/components/core_components.ex:155
#, elixir-autogen, elixir-format
msgid "We can't find the internet"
msgstr ""
#: lib/mv_web/components/core_components.ex:76
#: lib/mv_web/components/core_components.ex:130
#, elixir-autogen, elixir-format
msgid "close"
msgstr ""
#: lib/mv_web/member_live/form_component.ex:42
#: lib/mv_web/member_live/show.ex:24
#, elixir-autogen, elixir-format
msgid "Birth Date"
msgstr ""
#: lib/mv_web/member_live/form_component.ex:53
#: lib/mv_web/member_live/show.ex:36
#, elixir-autogen, elixir-format
msgid "Custom Properties"
msgstr ""
#: lib/mv_web/member_live/form_component.ex:46
#: lib/mv_web/member_live/show.ex:28
#, elixir-autogen, elixir-format
msgid "Exit Date"
msgstr ""
#: lib/mv_web/member_live/form_component.ex:50
#: lib/mv_web/member_live/show.ex:32
#, elixir-autogen, elixir-format
msgid "House Number"
msgstr ""
#: lib/mv_web/member_live/form_component.ex:47
#: lib/mv_web/member_live/show.ex:29
#, elixir-autogen, elixir-format
msgid "Notes"
msgstr ""
#: lib/mv_web/member_live/form_component.ex:43
#: lib/mv_web/member_live/show.ex:25
#, elixir-autogen, elixir-format
msgid "Paid"
msgstr ""
#: lib/mv_web/member_live/form_component.ex:44
#: lib/mv_web/member_live/show.ex:26
#, elixir-autogen, elixir-format
msgid "Phone Number"
msgstr ""
#: lib/mv_web/member_live/form_component.ex:51
#: lib/mv_web/member_live/show.ex:33
#, elixir-autogen, elixir-format
msgid "Postal Code"
msgstr ""
#: lib/mv_web/member_live/form_component.ex:73
#, elixir-autogen, elixir-format, fuzzy
msgid "Save Member"
msgstr ""
#: lib/mv_web/member_live/form_component.ex:73
#, elixir-autogen, elixir-format
msgid "Saving..."
msgstr ""
#: lib/mv_web/member_live/form_component.ex:49
#: lib/mv_web/member_live/show.ex:31
#, elixir-autogen, elixir-format
msgid "Street"
msgstr ""
#: lib/mv_web/member_live/form_component.ex:29
#, elixir-autogen, elixir-format
msgid "Use this form to manage member records and their properties."
msgstr ""
#: lib/mv_web/member_live/show.ex:50
#, elixir-autogen, elixir-format
msgid "Back to members"
msgstr ""
#: lib/mv_web/member_live/show.ex:14
#, elixir-autogen, elixir-format, fuzzy
msgid "Edit member"
msgstr ""
#: lib/mv_web/member_live/show.ex:20
#, elixir-autogen, elixir-format
msgid "Id"
msgstr ""
#: lib/mv_web/member_live/show.ex:25
#, elixir-autogen, elixir-format
msgid "No"
msgstr ""
#: lib/mv_web/member_live/show.ex:90
#, elixir-autogen, elixir-format, fuzzy
msgid "Show Member"
msgstr ""
#: lib/mv_web/member_live/show.ex:10
#, elixir-autogen, elixir-format
msgid "This is a member record from your database."
msgstr ""
#: lib/mv_web/member_live/show.ex:25
#, elixir-autogen, elixir-format
msgid "Yes"
msgstr ""
#: lib/mv_web/member_live/form_component.ex:107
#, elixir-autogen, elixir-format
msgid "Mitglied %{action} erfolgreich"
msgstr ""
#: lib/mv_web/member_live/form_component.ex:100
#, elixir-autogen, elixir-format
msgid "create"
msgstr ""
#: lib/mv_web/member_live/form_component.ex:101
#, elixir-autogen, elixir-format
msgid "update"
msgstr ""

View file

@ -110,3 +110,12 @@ msgstr ""
msgid "must be equal to %{number}"
msgstr ""
msgid "length must be greater than or equal to 5"
msgstr "length must be greater than or equal to 5"
msgid "cannot be before join date"
msgstr "cannot be before join date"
msgid "must consist of 5 digits"
msgstr "must consist of 5 digits"

View file

@ -0,0 +1,16 @@
defmodule MvWeb.MemberLive.IndexTest do
use MvWeb.ConnCase, async: true
import Phoenix.LiveViewTest
test "zeigt übersetzten Titel auf Deutsch", %{conn: conn} do
Gettext.put_locale(MvWeb.Gettext, "de")
{:ok, _view, html} = live(conn, "/members")
assert html =~ "Mitglieder" # Erwarteter deutscher Titel
end
test "shows translated title in English", %{conn: conn} do
Gettext.put_locale(MvWeb.Gettext, "en")
{:ok, _view, html} = live(conn, "/members")
assert html =~ "Members" # Erwarteter englischer Titel
end
end