defmodule Kanta.DeepL.Plugin.FormComponent do
@moduledoc """
Phoenix LiveComponent for Kanta translation form
"""
use Phoenix.LiveComponent
alias Kanta.DeepL.Adapter
alias KantaWeb.Components.Shared.Select
alias Kanta.Translations
alias Kanta.Translations.Message
alias Kanta.Translations.Locale.Finders.ListLocalesWithTranslatedMessage
alias Kanta.Translations.SingularTranslations.Finders.GetSingularTranslation
alias Kanta.Translations.PluralTranslations.Finders.GetPluralTranslation
def render(assigns) do
~H"""
DeepL Translator
<.form :let={form} for={@form} phx-change="change" phx-submit="submit" phx-target={@myself} class="space-y-4">
<.live_component
form={form}
module={Select}
id={"source_id"}
label="Source"
field={form["source_id"]}
options={[%{color: "#c3c3c3", label: "Message ID", value: nil}] ++ Enum.map(@locales, & %{color: "#c3c3c3", label: &1.name, value: &1.id})}
/>
Source text
DeepL Translation
Translate
Save
"""
end
def update(assigns, socket) do
locales_with_translation = ListLocalesWithTranslatedMessage.find(assigns.message)
socket =
socket
|> assign_new(:form, fn ->
%{
"source_text" => assigns.message.msgid,
"source_id" => nil
}
end)
|> assign(:locales, locales_with_translation)
{:ok, assign(socket, assigns)}
end
def handle_event("change", %{"source_id" => source_locale_id}, socket) do
source_iso_code =
unless is_nil(source_locale_id) do
Enum.find(socket.assigns.locales, &(&1.id == String.to_integer(source_locale_id))).iso639_code
end
source_text =
get_message_source_text(
socket.assigns.message,
String.to_integer(source_locale_id),
socket.assigns.translation
)
{:noreply,
update(
socket,
:form,
&Map.merge(&1, %{
"source_id" => source_locale_id,
"source_text" => source_text,
"source_iso_code" => source_iso_code
})
)}
end
def handle_event(
"submit",
%{"translated_text" => translated},
%{assigns: %{message: %Message{message_type: :singular}}} = socket
) do
locale = socket.assigns.locale
translation = socket.assigns.translation
Translations.update_singular_translation(translation, %{"translated_text" => translated})
{:noreply, socket}
end
def handle_event(
"submit",
%{"translated_text" => translated},
%{assigns: %{message: %Message{message_type: :plural}}} = socket
) do
locale = socket.assigns.locale
translation = socket.assigns.translation
Translations.update_plural_translation(translation, %{"translated_text" => translated})
{:noreply, socket}
end
def handle_event("translate_via_deep_l", _, socket) do
message = socket.assigns.message
source_locale = (socket.assigns.form["source_iso_code"] || "en") |> String.upcase()
source_text = socket.assigns.form["source_text"] || message.msgid
translate_locale = socket.assigns.locale
case Adapter.request_translation(
source_locale,
String.upcase(translate_locale.iso639_code),
source_text
) do
{:ok, translations} ->
%{"text" => translated_text} = List.first(translations)
{:noreply, update(socket, :form, &Map.merge(&1, %{"translated_text" => translated_text}))}
_ ->
{:noreply, socket}
end
end
defp get_message_source_text(
%Message{id: message_id, message_type: :singular},
locale_id,
_translation
) do
{:ok, translation} =
GetSingularTranslation.find(filter: [message_id: message_id, locale_id: locale_id])
translation.translated_text || translation.original_text
end
defp get_message_source_text(
%Message{id: message_id, message_type: :plural},
locale_id,
translation
) do
{:ok, translation} =
GetPluralTranslation.find(
filter: [
message_id: message_id,
locale_id: locale_id,
nplural_index: translation.nplural_index
]
)
translation.translated_text || translation.original_text
end
end