Initial commit

This commit is contained in:
2020-06-07 17:00:56 +03:00
commit f3b057a7be
32 changed files with 1096 additions and 0 deletions

28
lib/translitor/base.ex Normal file
View 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
View 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
View 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

View 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
View 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