Initial commit
This commit is contained in:
commit
f3b057a7be
4
.formatter.exs
Normal file
4
.formatter.exs
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
# Used by "mix format"
|
||||||
|
[
|
||||||
|
inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"]
|
||||||
|
]
|
28
.gitignore
vendored
Normal file
28
.gitignore
vendored
Normal 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
6
.iex.exs
Normal 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
21
README.md
Normal 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
19
config/config.exs
Normal 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
3
config/dev.exs
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
import Config
|
||||||
|
|
||||||
|
import_config "dev.secret.exs"
|
1
config/prod.exs
Normal file
1
config/prod.exs
Normal file
@ -0,0 +1 @@
|
|||||||
|
import Config
|
1
config/test.exs
Normal file
1
config/test.exs
Normal file
@ -0,0 +1 @@
|
|||||||
|
import Config
|
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
|
36
mix.exs
Normal file
36
mix.exs
Normal 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
18
mix.lock
Normal 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"},
|
||||||
|
}
|
66
test/data/translitor/be.txt
Normal file
66
test/data/translitor/be.txt
Normal 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
|
2
test/data/translitor/ru.txt
Normal file
2
test/data/translitor/ru.txt
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
Роман - Roman
|
||||||
|
Шевченко - Shevchenko
|
79
test/data/translitor/uk.txt
Normal file
79
test/data/translitor/uk.txt
Normal 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
|
8
test/localizator_test.exs
Normal file
8
test/localizator_test.exs
Normal 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
1
test/test_helper.exs
Normal file
@ -0,0 +1 @@
|
|||||||
|
ExUnit.start()
|
22
test/translitor_test/be_test.exs
Normal file
22
test/translitor_test/be_test.exs
Normal 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
|
22
test/translitor_test/ru_test.exs
Normal file
22
test/translitor_test/ru_test.exs
Normal 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
|
22
test/translitor_test/uk_test.exs
Normal file
22
test/translitor_test/uk_test.exs
Normal 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
|
Loading…
x
Reference in New Issue
Block a user