localizator/lib/translator/translator.ex

103 lines
2.9 KiB
Elixir

defmodule Localizator.Translator do
alias Localizator.Commons
alias Localizator.Direction
@typedoc """
Locale
"""
@type locale :: String.t()
@type from :: locale
@type from_may_be_nil :: from | nil
@type to :: locale
@type direction :: {from, to} | to | %{from: from, to: to} | %{to: to}
@type direction_map :: %{to: to, from: from_may_be_nil}
@typedoc """
Translation service
"""
@type translator :: Atom.t()
@typedoc """
Translation services list
"""
@type translators :: [translator]
@typedoc """
Translation resource
"""
@type resource :: String.t() | Map.t() | List.t()
@type source :: resource
@type result :: resource
@typedoc """
Error Message
"""
@type message :: String.t()
@spec list() :: translators
def list(), do: Application.get_env(:localizator, :translators)
@spec default() :: translator
def default(), do: list() |> List.first()
@spec translate(source, direction, translator) :: result
def translate(source, direction, translator \\ default()) do
map = Direction.get(direction)
translate(source, map.to, map.from, translator)
end
@spec translate(String.t(), to, from_may_be_nil, translator) :: result
def translate(string, to, from, translator) when is_binary(string) do
case Commons.is_html?(string) do
true -> translate_html(string, to, from, translator)
false -> translate_plain(string, to, from, translator)
end
end
@spec translate(Map.t(), to, from_may_be_nil, translator) :: result
def translate(map, to, from, translator) when is_map(map) do
Enum.map(map, fn {key, value} ->
{key, translate(value, to, from, translator)}
end)
|> Map.new()
end
@spec translate(List.t(), to, from_may_be_nil, translator) :: result
def translate(list, to, from, translator) when is_list(list) do
Enum.map(list, fn element -> translate(element, to, from, translator) end)
end
defp translate_plain(string, to, from, translator) do
translator.translate!(string, to, from)
end
defp translate_html(string, to, from, translator) do
string
|> Meeseeks.parse()
|> Meeseeks.tree()
|> translate_html_element(to, from, translator)
|> Meeseeks.parse(:tuple_tree)
|> Meeseeks.html()
end
# Plain Text Content
defp translate_html_element([element], to, from, translator) when is_binary(element) do
[translator.translate!(element, to, from)]
end
# Part of the Plain Text Content
defp translate_html_element(element, to, from, translator) when is_binary(element) do
translator.translate!(element, to, from)
end
# List of html elements
defp translate_html_element(elements, to, from, translator) when is_list(elements) do
Enum.map(elements, &translate_html_element(&1, to, from, translator))
end
# Html element
defp translate_html_element({tag, attributes, content}, to, from, translator) do
{tag, attributes, translate_html_element(content, to, from, translator)}
end
end