Initial commit

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

4
.formatter.exs Normal file
View File

@ -0,0 +1,4 @@
# Used by "mix format"
[
inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"]
]

28
.gitignore vendored Normal file
View File

@ -0,0 +1,28 @@
# The directory Mix will write compiled artifacts to.
/_build/
# If you run "mix test --cover", coverage assets end up here.
/cover/
# The directory Mix downloads your dependencies sources to.
/deps/
# Where third-party dependencies like ExDoc output generated docs.
/doc/
# Ignore .fetch files in case you like to edit your project deps locally.
/.fetch
# If the VM crashes, it generates a dump, let's ignore it too.
erl_crash.dump
# Also ignore archive artifacts (built via "mix archive.build").
*.ez
# Ignore package tarball (built via "mix hex.build").
localizator-*.tar
/config/*.secret.exs
# Ignore vscode config.
/.vscode/

6
.iex.exs Normal file
View File

@ -0,0 +1,6 @@
alias Localizator.Parser
alias Localizator.Parser.{Base, JSON}
alias Localizator.Translator
alias Localizator.Translator.{Yandex, Direction}
alias Localizator.Translitor
alias Localizator.Translitor.{UK, BE, RU}

21
README.md Normal file
View File

@ -0,0 +1,21 @@
# Localizator
**TODO: Add description**
## Installation
If [available in Hex](https://hex.pm/docs/publish), the package can be installed
by adding `localizator` to your list of dependencies in `mix.exs`:
```elixir
def deps do
[
{:localizator, "~> 0.1.0"}
]
end
```
Documentation can be generated with [ExDoc](https://github.com/elixir-lang/ex_doc)
and published on [HexDocs](https://hexdocs.pm). Once published, the docs can
be found at [https://hexdocs.pm/localizator](https://hexdocs.pm/localizator).

19
config/config.exs Normal file
View File

@ -0,0 +1,19 @@
use Mix.Config
# Configures Elixir's Logger
config :logger, :console,
format: "$time $metadata[$level] $message\n",
level: :info,
metadata: [:request_id]
config :localizator,
default_language: "en",
translators: [Localizator.Translator.Yandex],
translitors: [
Localizator.Translitor.BE,
Localizator.Translitor.RU,
Localizator.Translitor.UK
],
parsers: [Localizator.Parser.YAML, Localizator.Parser.JSON]
import_config "#{Mix.env()}.exs"

3
config/dev.exs Normal file
View File

@ -0,0 +1,3 @@
import Config
import_config "dev.secret.exs"

1
config/prod.exs Normal file
View File

@ -0,0 +1 @@
import Config

1
config/test.exs Normal file
View File

@ -0,0 +1 @@
import Config

18
lib/commons/commons.ex Normal file
View 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
View 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
View 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
View 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
View 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
View 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

View 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

View 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
View 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
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 (20122016)
"""
@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

36
mix.exs Normal file
View File

@ -0,0 +1,36 @@
defmodule Localizator.MixProject do
use Mix.Project
def project do
[
app: :localizator,
version: "0.1.0",
elixir: "~> 1.10",
start_permanent: Mix.env() == :prod,
deps: deps()
]
end
# Run "mix help compile.app" to learn about applications.
def application do
[
extra_applications: [:logger]
]
end
# Run "mix help deps" to learn about dependencies.
defp deps do
[
{:yandex_translate, "~> 0.4.0"},
# Parsers/generators
{:jason, "~> 1.2.1"},
{:yaml_elixir, "~> 2.4.0"},
# Remix for autorestart
{:ex_doc, "~> 0.21.3", only: :dev, runtime: false},
{:credo, "~> 1.4.0-rc.1", only: :dev, runtime: false},
{:remix, "~> 0.0.2", only: :dev}
]
end
end

18
mix.lock Normal file
View File

@ -0,0 +1,18 @@
%{
"bunt": {:hex, :bunt, "0.2.0", "951c6e801e8b1d2cbe58ebbd3e616a869061ddadcc4863d0a2182541acae9a38", [:mix], [], "hexpm", "7af5c7e09fe1d40f76c8e4f9dd2be7cebd83909f31fee7cd0e9eadc567da8353"},
"castore": {:hex, :castore, "0.1.6", "2da0dccb3eacb67841d11790598ff03cd5caee861e01fad61dce1376b5da28e6", [:mix], [], "hexpm", "f874c510b720d31dd6334e9ae5c859a06a3c9e67dfe1a195c512e57588556d3f"},
"credo": {:hex, :credo, "1.4.0", "92339d4cbadd1e88b5ee43d427b639b68a11071b6f73854e33638e30a0ea11f5", [:mix], [{:bunt, "~> 0.2.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "1fd3b70dce216574ce3c18bdf510b57e7c4c85c2ec9cad4bff854abaf7e58658"},
"earmark": {:hex, :earmark, "1.4.4", "4821b8d05cda507189d51f2caeef370cf1e18ca5d7dfb7d31e9cafe6688106a4", [:mix], [], "hexpm", "1f93aba7340574847c0f609da787f0d79efcab51b044bb6e242cae5aca9d264d"},
"ex_doc": {:hex, :ex_doc, "0.21.3", "857ec876b35a587c5d9148a2512e952e24c24345552259464b98bfbb883c7b42", [:mix], [{:earmark, "~> 1.4", [hex: :earmark, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}], "hexpm", "0db1ee8d1547ab4877c5b5dffc6604ef9454e189928d5ba8967d4a58a801f161"},
"jason": {:hex, :jason, "1.2.1", "12b22825e22f468c02eb3e4b9985f3d0cb8dc40b9bd704730efa11abd2708c44", [:mix], [{:decimal, "~> 1.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "b659b8571deedf60f79c5a608e15414085fa141344e2716fbd6988a084b5f993"},
"joken": {:hex, :joken, "2.2.0", "2daa1b12be05184aff7b5ace1d43ca1f81345962285fff3f88db74927c954d3a", [:mix], [{:jose, "~> 1.9", [hex: :jose, repo: "hexpm", optional: false]}], "hexpm", "b4f92e30388206f869dd25d1af628a1d99d7586e5cf0672f64d4df84c4d2f5e9"},
"jose": {:hex, :jose, "1.10.1", "16d8e460dae7203c6d1efa3f277e25b5af8b659febfc2f2eb4bacf87f128b80a", [:mix, :rebar3], [], "hexpm", "3c7ddc8a9394b92891db7c2771da94bf819834a1a4c92e30857b7d582e2f8257"},
"makeup": {:hex, :makeup, "1.0.2", "0b9f7bfb7a88bed961341b359bc2cc1b233517af891ba4890ec5a580ffe738b4", [:mix], [{:nimble_parsec, "~> 0.5", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "43833299231c6a6983afc75a34e43eeba638521d5527ff89809fa6372424fd7e"},
"makeup_elixir": {:hex, :makeup_elixir, "0.14.1", "4f0e96847c63c17841d42c08107405a005a2680eb9c7ccadfd757bd31dabccfb", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "f2438b1a80eaec9ede832b5c41cd4f373b38fd7aa33e3b22d9db79e640cbde11"},
"mint": {:hex, :mint, "1.0.0", "ca5ab33497ba2bdcc42f6cdd3927420a6159116be87c8173658e93c8746703da", [:mix], [{:castore, "~> 0.1.0", [hex: :castore, repo: "hexpm", optional: true]}], "hexpm", "b8943ef1e630879538dd6620bfc189d4d75fab3ad39f3fe9c50539879f7efd84"},
"nimble_parsec": {:hex, :nimble_parsec, "0.6.0", "32111b3bf39137144abd7ba1cce0914533b2d16ef35e8abc5ec8be6122944263", [:mix], [], "hexpm", "27eac315a94909d4dc68bc07a4a83e06c8379237c5ea528a9acff4ca1c873c52"},
"remix": {:hex, :remix, "0.0.2", "f06115659d8ede8d725fae1708920ef73353a1b39efe6a232d2a38b1f2902109", [:mix], [], "hexpm", "5f5555646ed4fca83fab8620735150aa0bc408c5a17a70d28cfa7086bc6f497c"},
"yamerl": {:hex, :yamerl, "0.8.0", "8214cfe16bbabe5d1d6c14a14aea11c784b9a21903dd6a7c74f8ce180adae5c7", [:rebar3], [], "hexpm", "010634477bf9c208a0767dcca89116c2442cf0b5e87f9c870f85cd1c3e0c2aab"},
"yaml_elixir": {:hex, :yaml_elixir, "2.4.0", "2f444abc3c994c902851fde56b6a9cb82895c291c05a0490a289035c2e62ae71", [:mix], [{:yamerl, "~> 0.7", [hex: :yamerl, repo: "hexpm", optional: false]}], "hexpm", "4e25a6d5c873e393689c6f1062c5ec90f6cd1be2527b073178ae37eae4c78bee"},
"yandex_translate": {:hex, :yandex_translate, "0.4.0", "a8851bdd0899d29334c9028aecc70c9921cae5dff86e512e30e72a0bceb6613a", [:mix], [{:castore, "~> 0.1.5", [hex: :castore, repo: "hexpm", optional: false]}, {:jason, "~> 1.2.0", [hex: :jason, repo: "hexpm", optional: false]}, {:joken, "~> 2.2.0", [hex: :joken, repo: "hexpm", optional: false]}, {:mint, "~> 1.0.0", [hex: :mint, repo: "hexpm", optional: false]}], "hexpm", "d4cdb333d8e447d0de20e0314ffc5fdd0a38421800866801007baca9102936f1"},
}

View File

@ -0,0 +1,66 @@
Ева - Jeva
Васiльева - Vasiljeva
Васiлёнак - Vasilionak
Ёрш - Jorsh
Вераб’ёў - Vierabjow
Салаўёва - Salawjova
Адъютантов - Adjutantov
Любоў - Liubow
В’юноў - Vjunow
Чарняк - Charniak
Лябецкая - Liabietskaja
Дар’я - Darja
Азаранка - Azaranka
Аліна - Alina
Багушэвіч - Bagushevich
Барыс - Barys
Вольскі - Volski
Віктар - Viktar
Галубовіч - Galubovich
Загорскі - Zagorski
Галіна - Galina
Дубко - Dubko
Дзмітры - Dzmitry
Дзмітрыева - Dzmitryjeva
Емяльянаў - Jemialjanaw
Жылуновіч - Zhylunovich
Жанна - Zhanna
Завальнюк - Zavalniuk
Зарына - Zaryna
Іваноўскі - Ivanowski
Ірына - Iryna
Шаройка - Sharojka
Красько - Krasko
Кацярына - Katsiaryna
Лінкевіч - Linkievich
Людміла - Liudmila
Масько - Masko
Марына - Maryna
Насовіч - Nasovich
Наталля - Natallia
Осцікавіч - Ostsikavich
Пятроўскі - Piatrowski
Павел - Paviel
Рыжонак - Ryzhonak
Раіса - Raisa
Смулькевіч - Smulkievich
Сяргей - Siargiej
Татарчук - Tatarchuk
Тамара - Tamara
Улашчык - Ulashchyk
Уладзімір - Uladzimir
Каўшоў - Kawshow
Станіслаў - Stanislaw
Сафонаў - Safonaw
Фёдар - Fiodar
Харытончык - Kharytonchyk
Цвірка - Tsvirka
Цімафей - Tsimafiej
Чарнoвіч - Charnovich
Часлаў - Chaslaw
Шашковіч - Shashkovich
Кашулёнак - Kashulionak
Кныровіч - Knyrovich
Валеры - Valiery
Эйсмант - Ejsmant
Эрык - Eryk

View File

@ -0,0 +1,2 @@
Роман - Roman
Шевченко - Shevchenko

View File

@ -0,0 +1,79 @@
Розгон - Rozghon
Згурський - Zghurskyi
Алушта - Alushta
Андрій - Andrii
Борщагівка - Borshchahivka
Борисенко - Borysenko
Вінниця - Vinnytsia
Володимир - Volodymyr
Гадяч - Hadiach
Богдан - Bohdan
Згурський - Zghurskyi
Згори - Zghory
Ґалаґан - Galagan
Ґорґани - Gorgany
Донецьк - Donetsk
Дмитро - Dmytro
Рівне - Rivne
Олег - Oleh
Есмань - Esman
Єнакієве - Yenakiieve
Гаєвич - Haievych
Короп'є - Koropie
Житомир - Zhytomyr
Жанна - Zhanna
Жежелів - Zhezheliv
Закарпаття - Zakarpattia
Казимирчук - Kazymyrchuk
Медвин - Medvyn
Михайленко - Mykhailenko
Іванків - Ivankiv
Іващенко - Ivashchenko
Їжакевич - Yizhakevych
Кадиївка - Kadyivka
Мар'їне - Marine
Йосипівна - Yosypivna
Стрий - Stryi
Олексій - Oleksii
Київ - Kyiv
Коваленко - Kovalenko
Лебедин - Lebedyn
Леонід - Leonid
Миколаїв - Mykolaiv
Маринич - Marynych
Ніжин - Nizhyn
Наталія - Nataliia
Одеса - Odesa
Онищенко - Onyshchenko
Полтава - Poltava
Петро - Petro
Розгон - Rozghon
Решетилівка - Reshetylivka
Рибчинський - Rybchynskyi
Суми - Sumy
Соломія - Solomiia
Тернопіль - Ternopil
Троць - Trots
Ужгород - Uzhhorod
Уляна - Uliana
Фастів - Fastiv
Філіпчук - Filipchuk
Харків - Kharkiv
Христина - Khrystyna
Біла Церква - Bila Tserkva
Стеценко - Stetsenko
Чернівці - Chernivtsi
Шевченко - Shevchenko
Шостка - Shostka
Кишеньки - Kyshenky
Щербухи - Shcherbukhy
Гоща - Hoshcha
Гаращенко - Harashchenko
Юрій - Yurii
Корюківка - Koriukivka
Яготин - Yahotyn
Ярошенко - Yaroshenko
Костянтин - Kostiantyn
Знам'янка - Znamianka
Феодосія - Feodosiia
Смартphone - Smartphone

View File

@ -0,0 +1,8 @@
defmodule LocalizatorTest do
use ExUnit.Case
doctest Localizator
test "greets the world" do
assert Localizator.hello() == :world
end
end

1
test/test_helper.exs Normal file
View File

@ -0,0 +1 @@
ExUnit.start()

View File

@ -0,0 +1,22 @@
defmodule Localizator.TranslitorTest.BETest do
alias Localizator.Translitor.BE
use ExUnit.Case
doctest Localizator.Translitor.BE
test "Sucess Belorussian translitaration" do
data = file_to_list("test/data/translitor/be.txt")
Enum.each(data, fn words ->
assert [cyrillic, latin] = String.split(words, " - "),
"Invalid input for tests. Expected two words separated by dash, got: #{words}"
assert latin == BE.convert(cyrillic)
end)
end
defp file_to_list(file) do
file
|> File.read!()
|> String.split("\n")
end
end

View File

@ -0,0 +1,22 @@
defmodule Localizator.TranslitorTest.RUTest do
alias Localizator.Translitor.RU
use ExUnit.Case
doctest Localizator.Translitor.RU
test "Sucess Russian translitaration" do
data = file_to_list("test/data/translitor/ru.txt")
Enum.each(data, fn words ->
assert [cyrillic, latin] = String.split(words, " - "),
"Invalid input for tests. Expected two words separated by dash, got: #{words}"
assert latin == RU.convert(cyrillic)
end)
end
defp file_to_list(file) do
file
|> File.read!()
|> String.split("\n")
end
end

View File

@ -0,0 +1,22 @@
defmodule Localizator.TranslitorTest.UKTest do
alias Localizator.Translitor.UK
use ExUnit.Case
doctest Localizator.Translitor.UK
test "Sucess Ukrainian translitaration" do
data = file_to_list("test/data/translitor/uk.txt")
Enum.each(data, fn words ->
assert [cyrillic, latin] = String.split(words, " - "),
"Invalid input for tests. Expected two words separated by dash, got: #{words}"
assert latin == UK.convert(cyrillic)
end)
end
defp file_to_list(file) do
file
|> File.read!()
|> String.split("\n")
end
end