Initial commit
This commit is contained in:
18
lib/commons/commons.ex
Normal file
18
lib/commons/commons.ex
Normal file
@@ -0,0 +1,18 @@
|
||||
defmodule Localizator.Commons do
|
||||
def struct_from_map(a_map, as: a_struct) do
|
||||
# Find the keys within the map
|
||||
keys =
|
||||
Map.keys(a_struct)
|
||||
|> Enum.filter(fn x -> x != :__struct__ end)
|
||||
|
||||
# Process map, checking for both string / atom keys
|
||||
processed_map =
|
||||
for key <- keys, into: %{} do
|
||||
value = Map.get(a_map, key) || Map.get(a_map, to_string(key))
|
||||
{key, value}
|
||||
end
|
||||
|
||||
a_struct = Map.merge(a_struct, processed_map)
|
||||
a_struct
|
||||
end
|
||||
end
|
||||
18
lib/localizator.ex
Normal file
18
lib/localizator.ex
Normal file
@@ -0,0 +1,18 @@
|
||||
defmodule Localizator do
|
||||
@moduledoc """
|
||||
Documentation for `Localizator`.
|
||||
"""
|
||||
|
||||
@doc """
|
||||
Hello world.
|
||||
|
||||
## Examples
|
||||
|
||||
iex> Localizator.hello()
|
||||
:world
|
||||
|
||||
"""
|
||||
def hello do
|
||||
:world
|
||||
end
|
||||
end
|
||||
20
lib/parser/base.ex
Normal file
20
lib/parser/base.ex
Normal file
@@ -0,0 +1,20 @@
|
||||
defmodule Localizator.Parser.Base do
|
||||
@typedoc """
|
||||
Text contents of the file for parse in Map
|
||||
"""
|
||||
@type contents :: String.t()
|
||||
|
||||
@typedoc """
|
||||
Data in Map format for encoding to text contents of the file
|
||||
"""
|
||||
@type data :: map
|
||||
|
||||
@typedoc """
|
||||
List of the file extensions for parser
|
||||
"""
|
||||
@type extensions :: [String.t()]
|
||||
|
||||
@callback parse(contents) :: {:ok, data} | {:error, any}
|
||||
@callback generate(data) :: {:ok, contents} | {:error, any}
|
||||
@callback extensions() :: {:ok, extensions}
|
||||
end
|
||||
25
lib/parser/json.ex
Normal file
25
lib/parser/json.ex
Normal file
@@ -0,0 +1,25 @@
|
||||
defmodule Localizator.Parser.JSON do
|
||||
@extensions ["json"]
|
||||
|
||||
@type contents :: String.t()
|
||||
@type data :: map
|
||||
@type extensions :: [String.t()]
|
||||
|
||||
@behaviour Localizator.Parser.Base
|
||||
|
||||
@impl true
|
||||
@spec parse(contents) :: {:ok, data} | {:error, atom | Jason.DecodeError.t()}
|
||||
def parse(contents) do
|
||||
Jason.decode(contents)
|
||||
end
|
||||
|
||||
@impl true
|
||||
@spec generate(data) :: {:ok, contents} | {:error, any}
|
||||
def generate(data) do
|
||||
Jason.encode(data)
|
||||
end
|
||||
|
||||
@impl true
|
||||
@spec extensions() :: {:ok, extensions}
|
||||
def extensions(), do: {:ok, @extensions}
|
||||
end
|
||||
42
lib/parser/yaml.ex
Normal file
42
lib/parser/yaml.ex
Normal file
@@ -0,0 +1,42 @@
|
||||
defmodule Localizator.Parser.YAML do
|
||||
@indent " "
|
||||
@extensions ["yml", "yaml"]
|
||||
|
||||
@type contents :: String.t()
|
||||
@type data :: map
|
||||
@type extensions :: [String.t()]
|
||||
|
||||
@behaviour Localizator.Parser.Base
|
||||
|
||||
@impl true
|
||||
@spec parse(contents) :: {:ok, data} | {:error, atom | Jason.DecodeError.t()}
|
||||
def parse(contents) do
|
||||
YamlElixir.read_from_string(contents)
|
||||
end
|
||||
|
||||
@impl true
|
||||
@spec generate(data) :: {:ok, contents} | {:error, any}
|
||||
def generate(data) do
|
||||
{:ok, to_yaml(data)}
|
||||
end
|
||||
|
||||
defp to_yaml(data, indentation \\ "") do
|
||||
data
|
||||
|> Map.keys()
|
||||
|> Enum.map(fn key ->
|
||||
Map.fetch!(data, key)
|
||||
|> value_to_yaml(key, indentation)
|
||||
end)
|
||||
|> Enum.join("\n")
|
||||
end
|
||||
|
||||
defp value_to_yaml(value, key, indentation) when is_number(value) or is_bitstring(value),
|
||||
do: "#{indentation}#{key}: #{value}"
|
||||
|
||||
defp value_to_yaml(value, key, indentation) when is_map(value),
|
||||
do: "#{indentation}#{key}:\n#{to_yaml(value, "#{indentation}#{@indent}")}"
|
||||
|
||||
@impl true
|
||||
@spec extensions() :: {:ok, extensions}
|
||||
def extensions(), do: {:ok, @extensions}
|
||||
end
|
||||
22
lib/translator/base.ex
Normal file
22
lib/translator/base.ex
Normal file
@@ -0,0 +1,22 @@
|
||||
defmodule Localizator.Translator.Base do
|
||||
@typedoc """
|
||||
Plain Text
|
||||
"""
|
||||
@type text :: String.t()
|
||||
|
||||
@typedoc """
|
||||
Locale
|
||||
"""
|
||||
@type locale :: String.t()
|
||||
@type from :: locale
|
||||
@type to :: locale
|
||||
|
||||
@typedoc """
|
||||
Error Message
|
||||
"""
|
||||
@type message :: String.t()
|
||||
|
||||
@callback detect(text) :: {:ok, locale} | {:error, message}
|
||||
@callback translate(text, to) :: {:ok, text} | {:error, message}
|
||||
@callback translate(text, to, from) :: {:ok, text} | {:error, message}
|
||||
end
|
||||
31
lib/translator/direction/direction.ex
Normal file
31
lib/translator/direction/direction.ex
Normal file
@@ -0,0 +1,31 @@
|
||||
defmodule Localizator.Translator.Direction do
|
||||
alias Localizator.Commons
|
||||
|
||||
defstruct [:from, :to]
|
||||
|
||||
@typedoc """
|
||||
Locale
|
||||
"""
|
||||
@type locale :: String.t() | Atom.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_struct :: %{to: to, from: from_may_be_nil}
|
||||
|
||||
@spec get(direction) :: direction_struct
|
||||
def get(direction) do
|
||||
direction_map =
|
||||
case direction do
|
||||
[from: from, to: to] -> %{to: "#{to}", from: "#{from}"}
|
||||
[from, to] -> %{to: "#{to}", from: "#{from}"}
|
||||
{from, to} -> %{to: "#{to}", from: "#{from}"}
|
||||
%{from: from, to: to} -> %{to: "#{to}", from: "#{from}"}
|
||||
%{to: to} -> %{to: "#{to}", from: nil}
|
||||
[to: to] -> %{to: "#{to}", from: nil}
|
||||
to -> %{to: "#{to}", from: nil}
|
||||
end
|
||||
|
||||
Commons.struct_from_map(direction_map, as: %__MODULE__{})
|
||||
end
|
||||
end
|
||||
47
lib/translator/translator.ex
Normal file
47
lib/translator/translator.ex
Normal file
@@ -0,0 +1,47 @@
|
||||
defmodule Localizator.Translator do
|
||||
alias Localizator.Translator.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) :: {:ok, result} | {:error, message}
|
||||
def translate(source, direction, translator \\ default()) do
|
||||
map = Direction.get(direction)
|
||||
translator.translate(source, map.to, map.from)
|
||||
end
|
||||
end
|
||||
40
lib/translator/yandex.ex
Normal file
40
lib/translator/yandex.ex
Normal file
@@ -0,0 +1,40 @@
|
||||
defmodule Localizator.Translator.Yandex do
|
||||
@type text :: String.t()
|
||||
@type locale :: String.t()
|
||||
@type from :: locale
|
||||
@type to :: locale
|
||||
@type message :: String.t()
|
||||
|
||||
@behaviour Localizator.Translator.Base
|
||||
|
||||
@impl true
|
||||
@spec detect(text) :: {:ok, locale} | {:error, message}
|
||||
def detect(text) when is_bitstring(text) do
|
||||
case YandexTranslate.detect(text) do
|
||||
%{languageCode: locale} -> {:ok, locale}
|
||||
%{} -> {:error, "Couldn't detect language"}
|
||||
end
|
||||
end
|
||||
|
||||
@impl true
|
||||
@spec translate(text, to) :: {:ok, text} | {:error, message}
|
||||
def translate(text, to, from \\ nil)
|
||||
|
||||
def translate(text, to, from) when is_bitstring(text) and is_bitstring(to) do
|
||||
translator_response =
|
||||
case from do
|
||||
nil -> YandexTranslate.translate(text, to)
|
||||
_ -> YandexTranslate.translate(text, to, from)
|
||||
end
|
||||
|
||||
case translator_response do
|
||||
%{translations: translations} ->
|
||||
translations
|
||||
|> List.first()
|
||||
|> Map.fetch(:text)
|
||||
|
||||
%{message: message} ->
|
||||
{:error, message}
|
||||
end
|
||||
end
|
||||
end
|
||||
28
lib/translitor/base.ex
Normal file
28
lib/translitor/base.ex
Normal file
@@ -0,0 +1,28 @@
|
||||
defmodule Localizator.Translitor.Base do
|
||||
@moduledoc """
|
||||
Base translit module. Describing behaviour for transliteration modules
|
||||
"""
|
||||
|
||||
@typedoc """
|
||||
Plain Text
|
||||
"""
|
||||
@type text :: String.t()
|
||||
|
||||
@typedoc """
|
||||
Translited Text
|
||||
"""
|
||||
@type translited :: String.t()
|
||||
|
||||
@typedoc """
|
||||
Locale
|
||||
"""
|
||||
@type locale :: String.t()
|
||||
|
||||
@typedoc """
|
||||
Error Message
|
||||
"""
|
||||
@type message :: String.t()
|
||||
|
||||
@callback convert(text) :: {:ok, translited} | {:error, message}
|
||||
@callback locale() :: {:ok, locale}
|
||||
end
|
||||
146
lib/translitor/be.ex
Normal file
146
lib/translitor/be.ex
Normal file
@@ -0,0 +1,146 @@
|
||||
defmodule Localizator.Translitor.BE do
|
||||
@moduledoc """
|
||||
Translit module for Belorussian language.
|
||||
"""
|
||||
@locale "be"
|
||||
@table %{
|
||||
"А" => "A",
|
||||
"Б" => "B",
|
||||
"В" => "V",
|
||||
"Г" => "G",
|
||||
"Д" => "D",
|
||||
"Ж" => "Zh",
|
||||
"З" => "Z",
|
||||
"И" => "I",
|
||||
"І" => "I",
|
||||
"Й" => "J",
|
||||
"К" => "K",
|
||||
"Л" => "L",
|
||||
"М" => "M",
|
||||
"Н" => "N",
|
||||
"О" => "O",
|
||||
"П" => "P",
|
||||
"Р" => "R",
|
||||
"С" => "S",
|
||||
"Т" => "T",
|
||||
"У" => "U",
|
||||
"Ф" => "F",
|
||||
"Х" => "Kh",
|
||||
"Ц" => "Ts",
|
||||
"Ч" => "Ch",
|
||||
"Ш" => "Sh",
|
||||
"Щ" => "Shch",
|
||||
"Ы" => "Y",
|
||||
"Э" => "E",
|
||||
"Ь" => "",
|
||||
"Ъ" => "",
|
||||
"Ў" => "W",
|
||||
"а" => "a",
|
||||
"б" => "b",
|
||||
"в" => "v",
|
||||
"г" => "g",
|
||||
"д" => "d",
|
||||
"ж" => "zh",
|
||||
"з" => "z",
|
||||
"и" => "i",
|
||||
"і" => "i",
|
||||
"й" => "j",
|
||||
"к" => "k",
|
||||
"л" => "l",
|
||||
"м" => "m",
|
||||
"н" => "n",
|
||||
"о" => "o",
|
||||
"п" => "p",
|
||||
"р" => "r",
|
||||
"с" => "s",
|
||||
"т" => "t",
|
||||
"у" => "u",
|
||||
"ф" => "f",
|
||||
"х" => "kh",
|
||||
"ц" => "ts",
|
||||
"ч" => "ch",
|
||||
"ш" => "sh",
|
||||
"щ" => "shch",
|
||||
"ы" => "y",
|
||||
"э" => "e",
|
||||
"ў" => "w",
|
||||
"ь" => "",
|
||||
"ъ" => "",
|
||||
"'" => "",
|
||||
"’" => ""
|
||||
}
|
||||
|
||||
@typedoc """
|
||||
Plain Text
|
||||
"""
|
||||
@type text :: String.t()
|
||||
|
||||
@typedoc """
|
||||
Locale
|
||||
"""
|
||||
@type locale :: String.t()
|
||||
|
||||
@behaviour Localizator.Translitor.Base
|
||||
|
||||
@impl true
|
||||
@spec locale() :: {:ok, locale}
|
||||
def locale(), do: @locale
|
||||
|
||||
@doc """
|
||||
A belorussian to english transliteration
|
||||
## Example
|
||||
``elixir
|
||||
iex> Localizator.Translitor.BE.convert("Ева Салаўёва")
|
||||
"Jeva Salawjova"
|
||||
``
|
||||
"""
|
||||
@impl true
|
||||
@spec convert(text) :: text
|
||||
def convert(text) when is_bitstring(text) do
|
||||
text
|
||||
|> String.graphemes()
|
||||
|> Enum.reduce([], &convert_letter/2)
|
||||
|> Enum.join()
|
||||
end
|
||||
|
||||
# special case for "<consonant>е", that should be mapped as "<translited consonant>ie"
|
||||
defp convert_letter(letter, acc)
|
||||
when letter in ~w(Е е Ё ё Ю ю Я я) do
|
||||
cond do
|
||||
List.last(acc) in ~w(B V G D Zh Z K L M N P R S T F Kh Ts Ch Sh Shch b v g d zh z k l m n p r s t f kh ts ch sh shch) ->
|
||||
acc ++ [convert_i(letter)]
|
||||
|
||||
List.last(acc) in (~w(A I J O U Y E W a i j o u y e w) ++ ["", " ", nil]) ->
|
||||
acc ++ [convert_j(letter)]
|
||||
end
|
||||
end
|
||||
|
||||
defp convert_letter(letter, acc) do
|
||||
acc ++ [convert_letter(letter)]
|
||||
end
|
||||
|
||||
defp convert_letter(letter) do
|
||||
case Map.get(@table, letter) do
|
||||
nil -> letter
|
||||
latin -> latin
|
||||
end
|
||||
end
|
||||
|
||||
defp convert_i("Е"), do: "Ie"
|
||||
defp convert_i("е"), do: "ie"
|
||||
defp convert_i("Ё"), do: "Io"
|
||||
defp convert_i("ё"), do: "io"
|
||||
defp convert_i("Ю"), do: "Iu"
|
||||
defp convert_i("ю"), do: "iu"
|
||||
defp convert_i("Я"), do: "Ia"
|
||||
defp convert_i("я"), do: "ia"
|
||||
|
||||
defp convert_j("Е"), do: "Je"
|
||||
defp convert_j("е"), do: "je"
|
||||
defp convert_j("Ё"), do: "Jo"
|
||||
defp convert_j("ё"), do: "jo"
|
||||
defp convert_j("Ю"), do: "Ju"
|
||||
defp convert_j("ю"), do: "ju"
|
||||
defp convert_j("Я"), do: "Ja"
|
||||
defp convert_j("я"), do: "ja"
|
||||
end
|
||||
114
lib/translitor/ru.ex
Normal file
114
lib/translitor/ru.ex
Normal file
@@ -0,0 +1,114 @@
|
||||
defmodule Localizator.Translitor.RU do
|
||||
@moduledoc """
|
||||
Translit module for Russian language. By ICAO Standard (2012—2016)
|
||||
"""
|
||||
@locale "ru"
|
||||
@table %{
|
||||
" " => " ",
|
||||
"А" => "A",
|
||||
"Б" => "B",
|
||||
"В" => "V",
|
||||
"Г" => "G",
|
||||
"Д" => "D",
|
||||
"Е" => "E",
|
||||
"Ё" => "E",
|
||||
"Ж" => "Zh",
|
||||
"З" => "Z",
|
||||
"И" => "I",
|
||||
"Й" => "I",
|
||||
"К" => "K",
|
||||
"Л" => "L",
|
||||
"М" => "M",
|
||||
"Н" => "N",
|
||||
"О" => "O",
|
||||
"П" => "P",
|
||||
"Р" => "R",
|
||||
"С" => "S",
|
||||
"Т" => "T",
|
||||
"У" => "U",
|
||||
"Ф" => "F",
|
||||
"Х" => "Kh",
|
||||
"Ц" => "Ts",
|
||||
"Ч" => "Ch",
|
||||
"Ш" => "Sh",
|
||||
"Щ" => "Shch",
|
||||
"Ъ" => "",
|
||||
"Ы" => "Y",
|
||||
"Ь" => "",
|
||||
"Э" => "E",
|
||||
"Ю" => "Iu",
|
||||
"Я" => "Ia",
|
||||
"а" => "a",
|
||||
"б" => "b",
|
||||
"в" => "v",
|
||||
"г" => "g",
|
||||
"д" => "d",
|
||||
"е" => "e",
|
||||
"ё" => "e",
|
||||
"ж" => "zh",
|
||||
"з" => "z",
|
||||
"и" => "i",
|
||||
"й" => "i",
|
||||
"к" => "k",
|
||||
"л" => "l",
|
||||
"м" => "m",
|
||||
"н" => "n",
|
||||
"о" => "o",
|
||||
"п" => "p",
|
||||
"р" => "r",
|
||||
"с" => "s",
|
||||
"т" => "t",
|
||||
"у" => "u",
|
||||
"ф" => "f",
|
||||
"х" => "kh",
|
||||
"ц" => "ts",
|
||||
"ч" => "ch",
|
||||
"ш" => "sh",
|
||||
"щ" => "shch",
|
||||
"ъ" => "",
|
||||
"ы" => "y",
|
||||
"ь" => "",
|
||||
"э" => "e",
|
||||
"ю" => "iu",
|
||||
"я" => "ia"
|
||||
}
|
||||
@typedoc """
|
||||
Plain Text
|
||||
"""
|
||||
@type text :: String.t()
|
||||
|
||||
@typedoc """
|
||||
Locale
|
||||
"""
|
||||
@type locale :: String.t()
|
||||
|
||||
@behaviour Localizator.Translitor.Base
|
||||
|
||||
@impl true
|
||||
@spec locale() :: {:ok, locale}
|
||||
def locale(), do: @locale
|
||||
|
||||
@doc """
|
||||
A russian to english transliteration
|
||||
## Example
|
||||
``elixir
|
||||
iex> Localizator.Translitor.RU.convert("Роман Шевченко")
|
||||
"Roman Shevchenko"
|
||||
``
|
||||
"""
|
||||
@impl true
|
||||
@spec convert(text) :: text
|
||||
def convert(text) when is_bitstring(text) do
|
||||
text
|
||||
|> String.graphemes()
|
||||
|> Enum.map(&convert_letter/1)
|
||||
|> Enum.join()
|
||||
end
|
||||
|
||||
defp convert_letter(letter) do
|
||||
case Map.get(@table, letter) do
|
||||
nil -> letter
|
||||
latin -> latin
|
||||
end
|
||||
end
|
||||
end
|
||||
47
lib/translitor/translitor.ex
Normal file
47
lib/translitor/translitor.ex
Normal file
@@ -0,0 +1,47 @@
|
||||
defmodule Localizator.Translitor do
|
||||
@typedoc """
|
||||
Locale
|
||||
"""
|
||||
@type locale :: String.t()
|
||||
@type to :: locale
|
||||
|
||||
@typedoc """
|
||||
Translitor service
|
||||
"""
|
||||
@type translitor :: Atom.t()
|
||||
|
||||
@typedoc """
|
||||
Transliters list
|
||||
"""
|
||||
@type translitors :: [translitor]
|
||||
|
||||
@typedoc """
|
||||
Translition resource
|
||||
"""
|
||||
@type resource :: String.t() | Map.t() | List.t()
|
||||
@type source :: resource
|
||||
@type result :: resource
|
||||
|
||||
@typedoc """
|
||||
Error Message
|
||||
"""
|
||||
@type message :: String.t()
|
||||
|
||||
@spec list() :: translitors
|
||||
def list(), do: Application.get_env(:localizator, :translitors)
|
||||
|
||||
defp translitors() do
|
||||
list()
|
||||
|> Enum.map(fn translitor -> {translitor.locale(), translitor} end)
|
||||
|> Map.new()
|
||||
end
|
||||
|
||||
@spec convert(source, locale) :: {:ok, result} | {:error, message}
|
||||
def convert(source, locale) do
|
||||
translitor =
|
||||
translitors()
|
||||
|> Map.get(locale)
|
||||
|
||||
translitor.convert(source)
|
||||
end
|
||||
end
|
||||
139
lib/translitor/uk.ex
Normal file
139
lib/translitor/uk.ex
Normal file
@@ -0,0 +1,139 @@
|
||||
defmodule Localizator.Translitor.UK do
|
||||
@moduledoc """
|
||||
Translit module for Ukrainian language.
|
||||
"""
|
||||
@locale "uk"
|
||||
@table %{
|
||||
"А" => "A",
|
||||
"Б" => "B",
|
||||
"В" => "V",
|
||||
"Г" => "H",
|
||||
"Ґ" => "G",
|
||||
"Д" => "D",
|
||||
"Е" => "E",
|
||||
"Є" => "Ye",
|
||||
"Ж" => "Zh",
|
||||
"З" => "Z",
|
||||
"И" => "Y",
|
||||
"І" => "I",
|
||||
"Ї" => "Yi",
|
||||
"Й" => "Y",
|
||||
"К" => "K",
|
||||
"Л" => "L",
|
||||
"М" => "M",
|
||||
"Н" => "N",
|
||||
"О" => "O",
|
||||
"П" => "P",
|
||||
"Р" => "R",
|
||||
"С" => "S",
|
||||
"Т" => "T",
|
||||
"У" => "U",
|
||||
"Ф" => "F",
|
||||
"Х" => "Kh",
|
||||
"Ц" => "Ts",
|
||||
"Ч" => "Ch",
|
||||
"Ш" => "Sh",
|
||||
"Щ" => "Shch",
|
||||
"Ю" => "Yu",
|
||||
"Я" => "Ya",
|
||||
"а" => "a",
|
||||
"б" => "b",
|
||||
"в" => "v",
|
||||
"г" => "h",
|
||||
"ґ" => "g",
|
||||
"д" => "d",
|
||||
"е" => "e",
|
||||
"є" => "ie",
|
||||
"ж" => "zh",
|
||||
"з" => "z",
|
||||
"и" => "y",
|
||||
"і" => "i",
|
||||
"ї" => "i",
|
||||
"й" => "i",
|
||||
"к" => "k",
|
||||
"л" => "l",
|
||||
"м" => "m",
|
||||
"н" => "n",
|
||||
"о" => "o",
|
||||
"п" => "p",
|
||||
"р" => "r",
|
||||
"с" => "s",
|
||||
"т" => "t",
|
||||
"у" => "u",
|
||||
"ф" => "f",
|
||||
"х" => "kh",
|
||||
"ц" => "ts",
|
||||
"ч" => "ch",
|
||||
"ш" => "sh",
|
||||
"щ" => "shch",
|
||||
"ю" => "iu",
|
||||
"я" => "ia"
|
||||
}
|
||||
|
||||
@typedoc """
|
||||
Plain Text
|
||||
"""
|
||||
@type text :: String.t()
|
||||
|
||||
@typedoc """
|
||||
Locale
|
||||
"""
|
||||
@type locale :: String.t()
|
||||
|
||||
@behaviour Localizator.Translitor.Base
|
||||
|
||||
@impl true
|
||||
@spec locale() :: {:ok, locale}
|
||||
def locale(), do: @locale
|
||||
|
||||
@doc """
|
||||
A ukrainian to english transliteration
|
||||
## Example
|
||||
``elixir
|
||||
iex> Localizator.Translitor.UK.convert("Данило Негрієнко")
|
||||
"Danylo Nehriienko"
|
||||
``
|
||||
"""
|
||||
@impl true
|
||||
@spec convert(text) :: text
|
||||
def convert(text) when is_binary(text) do
|
||||
text
|
||||
|> String.graphemes()
|
||||
|> Enum.reduce([], &convert_letter/2)
|
||||
|> Enum.join()
|
||||
end
|
||||
|
||||
# special case for "Зг", that should be mapped as "zgh"
|
||||
defp convert_letter(letter, [last_letter] = acc)
|
||||
when letter in ~w(Г г) and last_letter in ~w(z Z) do
|
||||
acc ++ [convert_gh(letter)]
|
||||
end
|
||||
|
||||
# special case for "зг", that should be mapped as "zgh"
|
||||
defp convert_letter(letter, acc) when letter in ~w(Г г) do
|
||||
case List.last(acc) do
|
||||
last_letter when last_letter in ~w(z Z) -> acc ++ [convert_gh(letter)]
|
||||
_ -> acc ++ [convert_letter(letter)]
|
||||
end
|
||||
end
|
||||
|
||||
defp convert_letter(letter, acc) do
|
||||
acc ++ [convert_letter(letter)]
|
||||
end
|
||||
|
||||
defp convert_letter(" "), do: " "
|
||||
defp convert_letter("ь"), do: ""
|
||||
defp convert_letter("Ь"), do: ""
|
||||
defp convert_letter("'"), do: ""
|
||||
defp convert_letter("’"), do: ""
|
||||
|
||||
defp convert_letter(letter) do
|
||||
case Map.get(@table, letter) do
|
||||
nil -> letter
|
||||
latin -> latin
|
||||
end
|
||||
end
|
||||
|
||||
defp convert_gh("Г"), do: "Gh"
|
||||
defp convert_gh("г"), do: "gh"
|
||||
end
|
||||
Reference in New Issue
Block a user