To avoid getting results like "... bla."</span>" -> "... bla</span>."" from Deepl we need to set set splitting_tags option to an element name (that's not as common as span).
106 lines
2.8 KiB
Elixir
106 lines
2.8 KiB
Elixir
defmodule Outlook.Translators do
|
|
@moduledoc """
|
|
The Translators context.
|
|
"""
|
|
|
|
import Ecto.Query, warn: false
|
|
alias Outlook.Repo
|
|
|
|
alias Outlook.InternalTree.TranslationUnit
|
|
alias Outlook.Translators.{DeeplAccount,Deepl}
|
|
alias OutlookWeb.HtmlDocComponent
|
|
|
|
def list_deepl_accounts do
|
|
Repo.all(DeeplAccount)
|
|
end
|
|
|
|
def get_deepl_account!(id), do: Repo.get!(DeeplAccount, id)
|
|
|
|
def get_deepl_auth_key(user) do
|
|
deepl_account_for_user(user)
|
|
|> select([:auth_key])
|
|
|> Repo.one()
|
|
|> Map.get(:auth_key)
|
|
end
|
|
|
|
def create_deepl_account(attrs \\ %{}) do
|
|
%DeeplAccount{}
|
|
|> DeeplAccount.changeset(attrs)
|
|
|> Repo.insert()
|
|
end
|
|
|
|
def update_deepl_account(%DeeplAccount{} = deepl_account, attrs) do
|
|
deepl_account
|
|
|> DeeplAccount.changeset(attrs)
|
|
|> Repo.update()
|
|
end
|
|
|
|
def delete_deepl_account(%DeeplAccount{} = deepl_account) do
|
|
Repo.delete(deepl_account)
|
|
end
|
|
|
|
def change_deepl_account(%DeeplAccount{} = deepl_account, attrs \\ %{}) do
|
|
DeeplAccount.changeset(deepl_account, attrs)
|
|
end
|
|
|
|
def increase_our_character_count(user, billed_characters) do
|
|
deepl_account_for_user(user)
|
|
|> Repo.update_all([inc: [our_character_count: billed_characters]])
|
|
end
|
|
|
|
def translate(translation, current_user) do
|
|
%{lang: target_lang,
|
|
article: %{content: article_tree, language: source_lang}
|
|
} = translation
|
|
article_as_html = prepare_article(article_tree)
|
|
auth_key = get_deepl_auth_key(current_user.id)
|
|
args = [
|
|
self(),
|
|
article_as_html,
|
|
%{
|
|
source_lang: source_lang,
|
|
target_lang: target_lang,
|
|
auth_key: auth_key
|
|
}
|
|
]
|
|
Task.start_link(Deepl, :translate, args)
|
|
end
|
|
|
|
defp deepl_account_for_user(user) when is_struct(user), do: deepl_account_for_user(user.id)
|
|
defp deepl_account_for_user(user_id) do
|
|
DeeplAccount |> where(user_id: ^user_id)
|
|
end
|
|
|
|
defp prepare_article(tree) do
|
|
# Logger.info "so far."
|
|
HtmlDocComponent.render_doc(%{tree: tree, tunit_tag: "tunit"})
|
|
|> Phoenix.HTML.Safe.to_iodata()
|
|
|> IO.iodata_to_binary()
|
|
end
|
|
|
|
def process_translation_result(result, tunit_ids) do
|
|
# TODO: update :our_character_count
|
|
process_translation(result.translation, tunit_ids)
|
|
end
|
|
|
|
def process_translation(translation, tunit_ids) do
|
|
tunit_map = translation
|
|
|> Floki.parse_fragment!
|
|
|> Floki.find("tunit")
|
|
|> Enum.map(fn {_,atts,cont} ->
|
|
%TranslationUnit{
|
|
nid: Enum.find(atts, fn {k,_} -> k == "nid" end) |> Tuple.to_list |> Enum.at(1),
|
|
content: Floki.raw_html(cont),
|
|
status: :untranslated
|
|
}
|
|
end)
|
|
|> Enum.map(fn tunit -> {tunit.nid, tunit} end)
|
|
|> Enum.into(%{})
|
|
|
|
case Enum.sort(Map.keys(tunit_map)) == Enum.sort(tunit_ids) do
|
|
true -> {:ok, tunit_map}
|
|
false -> {:error, "keys don't equal the originals"}
|
|
end
|
|
end
|
|
end
|