Packages

EctoGettext - library for localization Ecto validation errors with using Gettext

Current section

Files

Jump to
ecto_gettext lib ecto_gettext.ex
Raw

lib/ecto_gettext.ex

defmodule EctoGettext do
@moduledoc """
EctoGettext - library for localization Ecto validation errors with using Gettext
### Example:
import EctoGettext
localize_validations(MyApp.Gettext, errors)
"""
@doc """
Get a list of errors and return a new list with translated errors
"""
@spec localize_validations(module, list) :: list
def localize_validations(module, errors) do
errors
|> Enum.map(fn elem -> localize(module, elem) end)
end
@spec localize(module, tuple) :: {String.t, String.t}
defp localize(module, error) do
{attr, message} = error
{set_attr(module, attr), set_message(module, message)}
end
@spec numbers() :: list
defp numbers, do: ~w(0 1 2 3 4 5 6 7 8 9)
@spec set_attr(module, atom) :: String.t
defp set_attr(module, attr) do
attr =
attr
|> Atom.to_string
|> String.replace("_", " ")
|> String.capitalize
Gettext.dgettext(module, "attributes", attr)
end
@spec set_message(module, String.t) :: String.t
defp set_message(module, message) do
message = String.downcase(message)
if parse_number(message) do
cond do
String.starts_with?(message, "should be") ->
Gettext.dgettext(module, "errors", format_message(message, :should), count: parse_number(message))
String.starts_with?(message, "must be") ->
Gettext.dgettext(module, "errors", format_message(message, :must), count: parse_number(message))
true ->
Gettext.dgettext(module, "errors", message)
end
else
Gettext.dgettext(module, "errors", message)
end
end
@spec basic_formatting(String.t) :: list
defp basic_formatting(message) do
message
|> String.graphemes
|> Enum.filter(fn elem -> !Enum.member?(numbers, elem) end)
|> Enum.join
|> String.split(" ", trim: true)
end
@spec format_message(String.t, atom) :: String.t
defp format_message(message, type) when type == :should do
message = basic_formatting(message)
message = case Enum.count(message) do
5 ->
message
|> List.insert_at(4, "%{count}")
3 ->
message
|> List.insert_at(2, "%{count}")
end
Enum.join(message, " ")
end
defp format_message(message, type) when type == :must do
message = basic_formatting(message)
message
|> List.insert_at(Enum.count(message), "%{count}")
|> Enum.join(" ")
end
@spec parse_number(String.t) :: integer | nil
defp parse_number(message) do
message =
message
|> String.graphemes
|> Enum.filter(fn elem -> Enum.member?(numbers, elem) end)
|> Enum.join
case message do
"" ->
nil
_ ->
String.to_integer(message)
end
end
end