Initial commit

This commit is contained in:
Danil Negrienko 2020-06-19 08:45:38 +03:00
commit e8dad52c36
16 changed files with 488 additions and 0 deletions

32
.gitignore vendored Executable file
View File

@ -0,0 +1,32 @@
# The directory Mix will write compiled artifacts to.
/_build/
# The dialyzer directory.
/.elixir_ls/
# VSCode Artifacts
/.vscode/
# If you run "mix test --cover", coverage assets end up here.
/cover/
# The directory Mix downloads your dependencies sources to.
/deps/
# Where 3rd-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").
microsoft_translator-*.tar
/config/config.exs

1
.iex.exs Normal file
View File

@ -0,0 +1 @@
alias MicrosoftTranslator.Client

13
CHANGELOG.md Executable file
View File

@ -0,0 +1,13 @@
# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
## [0.1.0] - 2019-06-17
### Added
- initial version
### Modified
- code refactoring
- tests

87
README.md Executable file
View File

@ -0,0 +1,87 @@
<img align="right" width="50" height="50" src="assets/microsoft_translator.svg">
# Microsoft Translator
A simple Elixir interface to Microsoft Translator translation API in Azure. The Translator is a cloud-based machine translation service. The core service is the Translator, which powers a number of Microsoft products and services, and is used by thousands of businesses worldwide in their applications and workflows, which allows their content to reach a global audience.
## Installation
If [available in Hex](https://hex.pm/docs/publish), the package can be installed
by adding `microsoft_translator` to your list of dependencies in `mix.exs`:
```elixir
def deps do
[
{:microsoft_translator, "~> 0.1.0"}
]
end
```
## Get access to API
### Creating a account in the Microsoft Azure
To perform operations in Microsoft Azure via the API, you need to:
- [Sign in](https://ms.portal.azure.com/) to the Azure portal.
- Create a subscription for Translator. Create a resource in the **Search the Marketplace search box**, enter **Translator** and then select it.
- Select **Create** to define details for the subscription.
- From the **Pricing tier** list, select the pricing tier that best fits your needs.
- Select **Create** to finish creating the subscription.
### Getting a Authentication key
When you sign up for Translator, you get a personalized access key unique to your subscription. This key is required on each call to the Translator.
1. Retrieve your authentication key by first selecting the appropriate subscription.
1. Select **Keys** in the **Resource Management** section of your subscription's details.
1. Copy either of the keys listed for your subscription.
```elixir
config :microsoft_translator,
api_key: "KEY_1 or KEY_2"
endpoint: "ENDPOINT"
```
## Usage
### Supported languages
Request for getting list of supported languages is #languages.
```elixir
MicrosoftTranslator.languages()
```
### Language detection
Request for detecting language of text is #detect.
```elixir
MicrosoftTranslator.detect("Hello")
```
### Translation
Request for translating text is #translate.
```elixir
MicrosoftTranslator.translate("Hello", "uk")
```
## Contributing
Bug reports and pull requests are welcome on at https://gl.negrienko.com/negrienko/microsoft_translator.
## License
The hex is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
## Disclaimer
Use this package at your own peril and risk.
## Documentation
Documentation 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/microsoft_translator](https://hexdocs.pm/microsoft_translator).

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

View File

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="512px" height="512px" viewBox="0 0 512 512" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 52.6 (67491) - http://www.bohemiancoding.com/sketch -->
<title>microsoft_translator</title>
<desc>Created with Sketch.</desc>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="microsoft_translator">
<rect id="Rectangle-3-Copy-11" fill="#0063B1" x="0" y="0" width="512" height="512"></rect>
<path d="M175.619413,274.572516 C162.768213,274.572516 150.167324,279.760782 137.720036,290.307982 L130.933191,296.05376 L130.933191,271.517582 L132.509013,270.277404 C137.611947,266.261049 144.381724,262.898916 152.824036,260.139804 C161.237902,257.386382 169.208036,255.998293 176.728747,255.998293 C190.84288,255.998293 202.027236,260.46976 209.963236,269.435449 C217.813902,278.298738 221.66528,290.939449 221.66528,307.181227 L221.66528,393.146027 L202.072747,393.146027 L202.072747,377.330916 C198.756124,381.375716 194.870613,384.88576 190.421902,387.843982 C182.053547,393.419093 172.735147,396.218027 162.552036,396.218027 C149.541547,396.218027 139.017102,392.497493 131.211947,384.98816 C123.401102,377.484516 119.464391,367.927182 119.464391,356.583538 C119.464391,332.343182 135.711858,317.574827 166.750436,312.688071 L202.010169,307.448604 C201.213724,284.937671 192.566613,274.572516 175.619413,274.572516 Z M172.018347,330.431716 C159.434524,332.229404 150.770347,335.073849 146.116836,338.743182 C141.878613,342.093938 139.677013,347.748693 139.677013,356.088604 C139.677013,362.448782 141.725013,367.523271 145.883591,371.562382 C150.025102,375.590116 155.918791,377.643804 163.780836,377.643804 C174.783147,377.643804 183.77728,373.655893 191.04768,365.560604 C198.386347,357.385671 202.072747,346.798649 202.072747,333.606116 L202.072747,326.085404 L172.018347,330.431716 Z" id="Fill-1" fill="#FFFFFF" fill-rule="nonzero"></path>
<path d="M333.427924,351.51204 C331.627885,349.497697 330.0588,347.477775 328.708072,345.457853 L359.97779,317.438405 L280.791498,313.178154 C277.418176,313.178154 274.488564,315.643073 274.488564,319.004961 L270.222221,397.696839 L299.687702,371.468538 C326.013613,394.332162 365.821616,394.782738 392.592638,370.79337 C393.722211,369.671811 395.07014,368.553042 396.196914,367.434273 C374.595053,374.82903 349.628269,369.44722 333.427924,351.51204 Z" id="Shape" fill="#FFFFFF" transform="translate(333.209567, 355.437497) scale(-1, 1) translate(-333.209567, -355.437497) "></path>
<path d="M181.379158,167.249893 C179.57912,165.23555 178.010035,163.215628 176.659306,161.195706 L207.929024,133.176258 L128.742732,128.916008 C125.36941,128.916008 122.439799,131.380927 122.439799,134.742814 L118.173456,213.434692 L147.638936,187.206391 C173.964848,210.070015 213.77285,210.520591 240.543872,186.531223 C241.673445,185.409664 243.021375,184.290895 244.148148,183.172126 C222.546288,190.566883 197.579504,185.185074 181.379158,167.249893 Z" id="Shape-Copy" fill="#FFFFFF" transform="translate(181.160802, 171.175350) scale(-1, 1) rotate(-180.000000) translate(-181.160802, -171.175350) "></path>
<path d="M393.549938,133.172338 L397.668693,132.910649 L398.669938,149.23776 L394.579627,149.510827 C376.056604,150.739627 352.78336,151.575893 323.679004,152.099271 C323.24096,156.906382 322.899627,162.015004 322.62656,167.624249 C329.48736,166.253227 336.848782,165.587627 344.835982,165.587627 C347.043271,165.587627 349.193671,165.661582 351.332693,165.803804 L353.943893,155.569493 L370.288071,159.147804 L369.252693,163.272249 C368.780516,165.149582 368.376604,166.731093 367.779271,169.018027 C373.280427,170.821404 378.389049,173.415538 383.04256,176.749227 C395.666204,185.498738 402.083271,197.547804 402.083271,212.72576 C402.083271,228.159716 396.747093,240.709404 386.182827,249.788871 C376.466204,258.043449 362.545493,263.402382 344.722204,265.791716 L341.576249,266.212693 L335.142116,250.687716 L340.489671,249.99936 C355.195449,248.110649 366.243271,243.923627 373.684338,237.563449 C381.290382,231.021227 385.033671,222.880427 385.033671,212.72576 C385.033671,202.753138 380.795449,195.095893 372.131271,189.384249 C369.292516,187.53536 366.379804,186.079004 363.262293,184.952604 C358.369849,199.510471 352.47616,212.230827 345.484516,223.22176 C330.482916,246.699804 311.97696,258.709049 290.21696,258.709049 C281.25696,258.709049 274.094649,255.858916 269.105493,250.283804 C264.082204,244.896427 261.687182,237.358649 261.687182,227.949227 C261.687182,211.331982 269.509404,196.950471 284.988871,184.855893 C291.235271,179.872427 298.044871,175.867449 305.406293,172.835271 C305.588338,165.644516 305.969493,158.817849 306.566827,152.332516 C302.738204,152.343893 298.403271,152.366649 290.512782,152.41216 C280.13056,152.474738 274.811449,152.491804 268.468338,152.491804 L264.343893,152.491804 L264.343893,135.971271 L268.468338,135.971271 C275.004871,135.971271 280.494649,135.948516 291.002027,135.897316 C299.779982,135.846116 304.188871,135.82336 308.313316,135.811982 C309.041493,130.208427 309.991538,124.474027 311.231716,117.983004 L312.033849,113.778916 L328.810382,117.635982 L327.945671,121.618204 C326.955804,126.180693 326.165049,130.80576 325.556338,135.561671 C353.318116,135.061049 376.056604,134.258916 393.549938,133.172338 M344.835982,181.943182 C336.609849,181.943182 329.066382,182.82496 322.228338,184.582827 L322.228338,184.935538 C322.228338,199.243093 323.058916,212.06016 324.708693,223.307093 C326.847716,220.650382 328.963982,217.703538 331.057493,214.489316 C337.161671,204.875093 342.281671,194.106027 346.519893,181.948871 C346.013582,181.943182 345.456071,181.943182 344.835982,181.943182 M296.087893,197.604693 C284.419982,206.780871 278.736782,216.890027 278.736782,227.949227 C278.736782,238.126649 282.269582,242.353493 290.21696,242.353493 C296.867271,242.353493 303.295716,240.533049 309.655893,236.875093 C307.004871,223.625671 305.531449,208.436338 305.241316,191.381049 C301.970204,193.201493 298.926649,195.26656 296.087893,197.604693" id="Fill-1" fill="#FFFFFF" fill-rule="nonzero"></path>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

6
config/config.exs.example Executable file
View File

@ -0,0 +1,6 @@
# use Mix.Config
# config :microsoft_translator,
# api_key: "API_KEY"
# region: "REGION"
# endpoint: "ENDPOINT"

66
lib/microsoft_translator.ex Executable file
View File

@ -0,0 +1,66 @@
defmodule MicrosoftTranslator do
@moduledoc """
Basic functions for requests to Yandex Translate API on Yandex Cloud
"""
alias MicrosoftTranslator.Client
@doc """
Retrieves the list of supported languages.
Return a map with language code (use it for translations) and native language name
```elixir
%{
languages: [
%{code: "af", "name":"Afrikaans","nativeName":"Afrikaans"},
%{code: "ar", "name":"Arabic","nativeName":"العربية"},
%{code: "bg", "name":"Bulgarian","nativeName":"Български"},
%{code: "bn", "name":"Bangla","nativeName":"বাংলা"},
%{code: "bs", "name":"Bosnian","nativeName":"bosanski (latinica)"}
...
]
}
```
"""
def languages(), do: Client.call(:languages, %{})
@doc """
Detect the language of the text
Get text as a string param and return a map with language code
```elixir
MicrosoftTranslator.detect("Криївка")
# Response
%{languageCode: "uk"}
```
Or get a map with :text and :languageCodeHints (for specify the most likely languages).
> In some languages, one and the same word has the same spelling. For example, the English word hand is also written as hand in German, Swedish, and Dutch. If the text you transmit contains words like this, Translate may detect the source language incorrectly.
To avoid mistakes, you can use the languageCodeHints field to specify which languages should be given priority when determining the language of the text
```elixir
MicrosoftTranslator.detect(%{text: "Капелюх"})
# Response
%{languageCode: "uk"}
```
"""
def detect(params) when is_map(params), do: Client.call(:detect, params)
def detect(text) when is_binary(text), do: Client.call(:detect, %{text: text})
def translate(params) when is_map(params), do: Client.call(:translate, params)
def translate(text, to) when is_binary(text) and is_binary(to),
do: Client.call(:translate, %{text: text, to: to})
def translate(text, to, from)
when is_binary(text) and is_binary(to) and is_binary(from),
do:
Client.call(:translate, %{
text: text,
to: to,
from: from
})
end

View File

@ -0,0 +1,12 @@
defmodule MicrosoftTranslator.Auth.ApiKey do
def get_auth_headers(%{api_key: api_key, region: region}) do
[
{"Ocp-Apim-Subscription-Key", api_key},
{"Ocp-Apim-Subscription-Region", region}
]
end
def get_auth_headers(%{api_key: api_key}) do
[{"Ocp-Apim-Subscription-Key", api_key}]
end
end

View File

@ -0,0 +1,10 @@
defmodule MicrosoftTranslator.Auth do
alias MicrosoftTranslator.Auth.{ApiKey}
defp get_config(), do: Application.get_all_env(:microsoft_translator) |> Map.new()
def authorization_headers(config \\ get_config())
def authorization_headers(%{api_key: _} = params),
do: ApiKey.get_auth_headers(params)
end

View File

@ -0,0 +1,150 @@
defmodule MicrosoftTranslator.Client do
@empty_state %{data: [], done: false}
@base_host "api.cognitive.microsofttranslator.com"
@base_path "/"
@api_methods %{
languages: %{
method: "GET",
path: "languages"
},
detect: %{
method: "POST",
path: "detect"
},
translate: %{
method: "POST",
path: "translate"
}
}
@api_default_params %{
"api-version" => "3.0"
}
@availaible_api_methods Map.keys(@api_methods)
@default_headers [{"Content-Type", "application/json"}]
alias MicrosoftTranslator.Auth
def call(api_method \\ :languages, args \\ %{})
when api_method in @availaible_api_methods and is_map(args) do
body = generate_body(api_method, args)
headers = generate_headers()
params = generate_params(api_method, args)
api_method
|> fetch(headers, body, params)
|> parse(api_method)
end
defp generate_headers(headers \\ [])
defp generate_headers(header) when is_tuple(header),
do: generate_headers([header])
defp generate_headers(headers) when is_list(headers),
do: @default_headers ++ Auth.authorization_headers() ++ headers
defp generate_params(:translate, params) do
params
|> Map.take([:to, :from])
|> params_to_string()
end
defp generate_params(api_method, _params) when api_method in [:detect, :languages],
do: params_to_string(%{})
defp params_to_string(params_map) do
params_map
|> Map.merge(@api_default_params)
|> Enum.reduce("", fn {key, value}, acc -> acc <> "&" <> "#{key}" <> "=" <> "#{value}" end)
|> String.replace_leading("&", "?")
end
defp generate_body(method, params), do: transform_body(method, params) |> Jason.encode!()
defp transform_body(:languages, _), do: %{}
defp transform_body(method, params) when method in [:detect, :translate],
do: [%{text: Map.fetch!(params, :text)}]
defp transform_body(_, params), do: params
defp parse({:ok, %{data: body}}, api_method) do
Jason.decode!(body, keys: :atoms)
|> transform_response(api_method)
end
defp transform_response(response, :detect) do
result =
response
|> List.first()
|> Map.fetch(:language)
case result do
{:ok, language} -> %{languageCode: language}
end
end
defp transform_response(response, :translate) do
result =
response
|> List.first()
|> Map.take([:translations])
end
defp transform_response(response, :languages) do
%{dictionary: dictionary} = response
dictionary
|> Enum.map(fn {key, %{name: name, nativeName: native, dir: dir}} ->
%{code: "#{key}", name: name, nativeName: native, dir: dir}
end)
end
def fetch(api_method, headers, body, params) do
method = @api_methods[api_method].method
path = @base_path <> @api_methods[api_method].path <> params
with {:ok, conn} <- Mint.HTTP.connect(:https, @base_host, 443),
{:ok, conn, _ref} <- Mint.HTTP.request(conn, method, path, headers, body) do
handle_response(conn, @empty_state)
end
end
defp handle_response(conn, state) do
receive do
message ->
case Mint.HTTP.stream(conn, message) do
{:ok, conn, responses} ->
case Enum.reduce(responses, state, &handle_res/2) do
# Loop ends here
%{done: true} = state -> {:ok, state}
%{done: false} = state -> handle_response(conn, state)
end
{:error, _, reason, _} ->
{:error, reason}
:unknown ->
exit({:unexpected, message})
end
end
end
defp handle_res({:status, _, status}, state),
do: Map.put(state, :status, status)
defp handle_res({:headers, _, headers}, state),
do: Map.put(state, :headers, headers)
defp handle_res({:data, _, data}, state),
do: Map.update!(state, :data, fn acc -> [data | acc] end)
defp handle_res({:done, _}, state) do
Map.update!(state, :data, fn acc ->
acc
|> Enum.reverse()
|> Enum.join("")
end)
|> Map.put(:done, true)
end
end

64
mix.exs Executable file
View File

@ -0,0 +1,64 @@
defmodule MicrosoftTranslator.MixProject do
use Mix.Project
@name "MicrosoftTranslator"
@version "0.4.0"
# @repo_url "https://github.com/negrienko/microsoft_translator"
@repo_url "https://gl.negrienko.com/negrienko/microsoft_translator"
@homepage_url "https://negrienko.com/all/microsoft-translator/"
@author_url "https://negrienko.com/"
@description """
Translate word and phrases using the Microsoft Translator API. See README.md for information.
"""
def project do
[
app: :microsoft_translator,
version: @version,
elixir: "~> 1.9",
build_embedded: Mix.env() == :prod,
start_permanent: Mix.env() == :prod,
package: package(),
deps: deps(),
# Docs
name: @name,
description: @description,
source_url: @repo_url,
homepage_url: @homepage_url,
docs: [
logo: "assets/microsoft_translator.svg",
main: @name,
source_ref: @version,
source_url: @repo_url
]
]
end
def application do
[extra_applications: applications(Mix.env())]
end
defp applications(:dev), do: applications(:all) ++ [:remix]
defp applications(_all), do: [:logger, :jose]
defp deps do
[
{:joken, "~> 2.2.0"},
{:jose, "~> 1.10.1"},
{:jason, "~> 1.2.0"},
{:mint, "~> 1.1.0"},
{:castore, "~> 0.1.6"},
{:ex_spec, "~> 2.0.1", only: :test},
{:ex_doc, "~> 0.21.3", only: :dev},
{:remix, "~> 0.0.2", only: :dev}
]
end
defp package do
[
maintainers: ["Danylo Negriienko"],
licenses: ["MIT"],
links: %{"git" => @repo_url, "author" => @author_url, "homepage" => @homepage_url}
]
end
end

28
mix.lock Normal file
View File

@ -0,0 +1,28 @@
%{
"base64url": {:hex, :base64url, "0.0.1", "36a90125f5948e3afd7be97662a1504b934dd5dac78451ca6e9abf85a10286be", [:rebar], [], "hexpm"},
"castore": {:hex, :castore, "0.1.6", "2da0dccb3eacb67841d11790598ff03cd5caee861e01fad61dce1376b5da28e6", [:mix], [], "hexpm", "f874c510b720d31dd6334e9ae5c859a06a3c9e67dfe1a195c512e57588556d3f"},
"certifi": {:hex, :certifi, "2.5.1", "867ce347f7c7d78563450a18a6a28a8090331e77fa02380b4a21962a65d36ee5", [:rebar3], [{:parse_trans, "~>3.3", [hex: :parse_trans, repo: "hexpm", optional: false]}], "hexpm"},
"earmark": {:hex, :earmark, "1.4.3", "364ca2e9710f6bff494117dbbd53880d84bebb692dafc3a78eb50aa3183f2bfd", [:mix], [], "hexpm", "8cf8a291ebf1c7b9539e3cddb19e9cef066c2441b1640f13c34c1d3cfc825fec"},
"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"},
"ex_spec": {:hex, :ex_spec, "2.0.1", "8bdbd6fa85995fbf836ed799571d44be6f9ebbcace075209fd0ad06372c111cf", [:mix], [], "hexpm", "b44fe5054497411a58341ece5bf7756c219d9d6c1303b5ac467f557a0a4c31ac"},
"hackney": {:hex, :hackney, "1.15.1", "9f8f471c844b8ce395f7b6d8398139e26ddca9ebc171a8b91342ee15a19963f4", [:rebar3], [{:certifi, "2.5.1", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "6.0.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "1.0.1", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "~>1.1", [hex: :mimerl, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "1.1.4", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}], "hexpm"},
"httpoison": {:hex, :httpoison, "1.5.1", "0f55b5b673b03c5c327dac7015a67cb571b99b631acc0bc1b0b98dcd6b9f2104", [:mix], [{:hackney, "~> 1.8", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm"},
"idna": {:hex, :idna, "6.0.0", "689c46cbcdf3524c44d5f3dde8001f364cd7608a99556d8fbd8239a5798d4c10", [:rebar3], [{:unicode_util_compat, "0.4.1", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm"},
"jason": {:hex, :jason, "1.2.0", "10043418c42d2493d0ee212d3fddd25d7ffe484380afad769a0a38795938e448", [:mix], [{:decimal, "~> 1.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "116747dbe057794c3a3e4e143b7c8390b29f634e16c78a7f59ba75bfa6852e7f"},
"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.1", "82f332e461dc6c79dbd82fbe2a9c10d48ed07146f0a478286e590c83c52010b5", [:mix], [{:nimble_parsec, "~> 0.5.0", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "49736fe5b66a08d8575bf5321d716bac5da20c8e6b97714fec2bcd6febcfa1f8"},
"makeup_elixir": {:hex, :makeup_elixir, "0.14.0", "cf8b7c66ad1cff4c14679698d532f0b5d45a3968ffbcbfd590339cb57742f1ae", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "d4b316c7222a85bbaa2fd7c6e90e37e953257ad196dc229505137c5e505e9eff"},
"metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], [], "hexpm"},
"mimerl": {:hex, :mimerl, "1.2.0", "67e2d3f571088d5cfd3e550c383094b47159f3eee8ffa08e64106cdf5e981be3", [:rebar3], [], "hexpm"},
"mint": {:hex, :mint, "1.1.0", "1fd0189edd9e3ffdbd7fcd8bc3835902b987a63ec6c4fd1aa8c2a56e2165f252", [:mix], [{:castore, "~> 0.1.0", [hex: :castore, repo: "hexpm", optional: true]}], "hexpm", "5bfd316c3789340b682d5679a8116bcf2112e332447bdc20c1d62909ee45f48d"},
"mojito": {:hex, :mojito, "0.3.0", "806cd3c1832333a9ee784e7ea2799863fbe4de55ecb4623a8f4ef870c2844cc6", [:mix], [{:castore, "~> 0.1", [hex: :castore, repo: "hexpm", optional: false]}, {:mint, "~> 0.2.1", [hex: :mint, repo: "hexpm", optional: false]}, {:poolboy, "~> 1.5", [hex: :poolboy, repo: "hexpm", optional: false]}], "hexpm"},
"nimble_parsec": {:hex, :nimble_parsec, "0.5.3", "def21c10a9ed70ce22754fdeea0810dafd53c2db3219a0cd54cf5526377af1c6", [:mix], [], "hexpm", "589b5af56f4afca65217a1f3eb3fee7e79b09c40c742fddc1c312b3ac0b3399f"},
"ojson": {:hex, :ojson, "1.0.0", "fd28614eadaec00a15cdb2f53f29d8717a812a508ddb80d202f2f2e2aaeabbcc", [:mix, :rebar3], [], "hexpm"},
"parse_trans": {:hex, :parse_trans, "3.3.0", "09765507a3c7590a784615cfd421d101aec25098d50b89d7aa1d66646bc571c1", [:rebar3], [], "hexpm"},
"poison": {:hex, :poison, "3.1.0", "d9eb636610e096f86f25d9a46f35a9facac35609a7591b3be3326e99a0484665", [:mix], [], "hexpm"},
"poolboy": {:hex, :poolboy, "1.5.2", "392b007a1693a64540cead79830443abf5762f5d30cf50bc95cb2c1aaafa006b", [:rebar3], [], "hexpm"},
"remix": {:hex, :remix, "0.0.2", "f06115659d8ede8d725fae1708920ef73353a1b39efe6a232d2a38b1f2902109", [:mix], [], "hexpm", "5f5555646ed4fca83fab8620735150aa0bc408c5a17a70d28cfa7086bc6f497c"},
"ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.4", "f0eafff810d2041e93f915ef59899c923f4568f4585904d010387ed74988e77b", [:make, :mix, :rebar3], [], "hexpm"},
"unicode_util_compat": {:hex, :unicode_util_compat, "0.4.1", "d869e4c68901dd9531385bb0c8c40444ebf624e60b6962d95952775cac5e90cd", [:rebar3], [], "hexpm"},
}

1
test/test_helper.exs Executable file
View File

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

3
test/yandex_translate_test.exs Executable file
View File

@ -0,0 +1,3 @@
defmodule YandexTranslatorTest do
use ExUnit.Case
end