翻译Ecto验证消息

时间:2017-05-25 15:10:09

标签: elixir phoenix-framework ecto

我的凤凰应用程序中有以下架构:

defmodule TattooBackend.Accounts.Account do
  @moduledoc """
  Contains schema and changesets for Account resource.
  """

  use Ecto.Schema

  import Ecto.Changeset

  alias TattooBackend.Accounts.Account

  schema "accounts" do
    field :email, :string
    field :crypted_password, :string
    field :password, :string, virtual: true
    timestamps()
  end

  def changeset(%Account{} = user, attributes \\ %{}) do
    user
    |> cast(attributes, [:email, :password])
    |> validate_required([:email, :password])
    |> validate_length(:password, min: 6)
    |> validate_format(:email, ~r/([\w-\.]+)@((?:[\w]+\.)+)([a-zA-Z]{2,4})/)
    |> unique_constraint(:email, name: "accounts_lower_email_index")
    |> put_password_hash
  end

  defp put_password_hash(changeset) do
    case changeset do
      %Ecto.Changeset{valid?: true, changes: %{password: pass}} ->
        put_change(changeset, :crypted_password, Comeonin.Bcrypt.hashpwsalt(pass))
      _ ->
        changeset
    end
  end
end

我写了一个简单的测试:

defmodule TattooBackend.Accounts.AccountTest do
  use TattooBackend.DataCase, async: true

  alias TattooBackend.Repo
  alias TattooBackend.Accounts.Account

  describe "with invalid attributes" do
    setup do
      changeset = Account.changeset(%Account{})

      {:ok, %{changeset: changeset}}
    end

    test "changeset is inalid", %{changeset: changeset} do
      refute changeset.valid?
    end

    test "changeset have errors", %{changeset: changeset} do
      assert changeset.errors == [
        email:      {"can't be blank", [validation: :required]},
        password:   {"can't be blank", [validation: :required]},
      ]
    end
  end
end

现在我的问题是如何翻译这些Ecto验证消息?

1 个答案:

答案 0 :(得分:1)

您可以列举错误并使用Gettext进行翻译。例如

def translate_error(%{errors: errors}=_changeset) do
    Enum.map(errors, fn {field, error} ->
      Atom.to_string(field) <> " " <> translate_error(error)
    end)
end
def translate_error({msg, opts}) do
    case opts[:count] do
      nil -> Gettext.dgettext(TattooBackendWeb.Gettext, "errors", msg, opts)
      count -> Gettext.dngettext(TattooBackendWeb.Gettext, "errors", msg, msg, count, opts)
    end
end

这应该打印如下内容:

["email has already been taken", "password can't be blank"]

希望有帮助!