diff --git a/lib/ash/changeset/changeset.ex b/lib/ash/changeset/changeset.ex index 5db5d6d2b..2730c61f8 100644 --- a/lib/ash/changeset/changeset.ex +++ b/lib/ash/changeset/changeset.ex @@ -388,6 +388,7 @@ defmodule Ash.Changeset do require Ash.Tracer import Ash.Expr + import Ash.Gettext require Logger defmodule OriginalDataNotAvailable do @@ -3491,7 +3492,7 @@ defmodule Ash.Changeset do changeset, InvalidAttribute.exception( field: key, - message: "cannot be changed", + message: error_message("cannot be changed"), value: changeset.attributes[key] ) ) @@ -5927,7 +5928,7 @@ defmodule Ash.Changeset do error = InvalidRelationship.exception( relationship: relationship.name, - message: "relationship is not editable" + message: error_message("relationship is not editable") ) add_error(changeset, error) @@ -5936,7 +5937,7 @@ defmodule Ash.Changeset do error = InvalidRelationship.exception( relationship: relationship.name, - message: "cannot manage a manual relationship" + message: error_message("cannot manage a manual relationship") ) add_error(changeset, error) @@ -6026,7 +6027,7 @@ defmodule Ash.Changeset do changeset, InvalidRelationship.exception( relationship: relationship.name, - message: "cannot provide structs that don't match the destination" + message: error_message("cannot provide structs that don't match the destination") ) ) else diff --git a/lib/ash/resource/change/cascade_destroy.ex b/lib/ash/resource/change/cascade_destroy.ex index 15978e255..2f8cb5464 100644 --- a/lib/ash/resource/change/cascade_destroy.ex +++ b/lib/ash/resource/change/cascade_destroy.ex @@ -95,6 +95,7 @@ defmodule Ash.Resource.Change.CascadeDestroy do """ use Ash.Resource.Change + import Ash.Gettext require Ash.Query @doc false @@ -245,7 +246,7 @@ defmodule Ash.Resource.Change.CascadeDestroy do {:error, Ash.Error.Changes.InvalidRelationship.exception( relationship: opts.relationship, - message: "Relationship doesn't exist." + message: error_message("Relationship doesn't exist.") )} relationship -> diff --git a/lib/ash/resource/change/cascade_update.ex b/lib/ash/resource/change/cascade_update.ex index 3c580505d..87ad4231b 100644 --- a/lib/ash/resource/change/cascade_update.ex +++ b/lib/ash/resource/change/cascade_update.ex @@ -88,6 +88,7 @@ defmodule Ash.Resource.Change.CascadeUpdate do """ use Ash.Resource.Change + import Ash.Gettext require Ash.Query @doc false @@ -177,7 +178,7 @@ defmodule Ash.Resource.Change.CascadeUpdate do {:error, Ash.Error.Changes.InvalidRelationship.exception( relationship: opts.relationship, - message: "Relationship doesn't exist." + message: error_message("Relationship doesn't exist.") )} {_, false} -> diff --git a/lib/ash/resource/change/relate_actor.ex b/lib/ash/resource/change/relate_actor.ex index e5861314d..49b1de8d0 100644 --- a/lib/ash/resource/change/relate_actor.ex +++ b/lib/ash/resource/change/relate_actor.ex @@ -5,6 +5,7 @@ defmodule Ash.Resource.Change.RelateActor do @moduledoc false use Ash.Resource.Change + import Ash.Gettext alias Ash.Changeset alias Ash.Error.Changes.InvalidRelationship @@ -61,7 +62,10 @@ defmodule Ash.Resource.Change.RelateActor do changeset, InvalidRelationship.exception( relationship: relationship.name, - message: "could not relate to actor, as no actor was found (and :allow_nil? is false)" + message: + error_message( + "could not relate to actor, as no actor was found (and :allow_nil? is false)" + ) ) ) diff --git a/lib/ash/type/atom.ex b/lib/ash/type/atom.ex index 2edf6bda4..28082b47b 100644 --- a/lib/ash/type/atom.ex +++ b/lib/ash/type/atom.ex @@ -25,6 +25,7 @@ defmodule Ash.Type.Atom do #{Spark.Options.docs(@constraints)} """ use Ash.Type + import Ash.Gettext @impl true def storage_type(_), do: :string @@ -55,7 +56,7 @@ defmodule Ash.Type.Atom do else [ [ - message: "atom must be one of %{atom_list}, got: %{value}", + message: error_message("atom must be one of %{atom_list}, got: %{value}"), atom_list: Enum.join(atom_list, ", "), value: value ] diff --git a/lib/ash/type/ci_string.ex b/lib/ash/type/ci_string.ex index b649da9f8..ce12f31fc 100644 --- a/lib/ash/type/ci_string.ex +++ b/lib/ash/type/ci_string.ex @@ -53,6 +53,7 @@ defmodule Ash.Type.CiString do #{Spark.Options.docs(@constraints)} """ use Ash.Type + import Ash.Gettext @impl true def storage_type(_), do: :ci_string @@ -172,7 +173,13 @@ defmodule Ash.Type.CiString do Enum.reduce(constraints, [], fn {:max_length, max_length}, errors -> if String.length(value) > max_length do - [[message: "length must be less than or equal to %{max}", max: max_length] | errors] + [ + [ + message: error_message("length must be less than or equal to %{max}"), + max: max_length + ] + | errors + ] else errors end @@ -180,7 +187,10 @@ defmodule Ash.Type.CiString do {:min_length, min_length}, errors -> if String.length(value) < min_length do [ - [message: "length must be greater than or equal to %{min}", min: min_length] + [ + message: error_message("length must be greater than or equal to %{min}"), + min: min_length + ] | errors ] else @@ -200,7 +210,10 @@ defmodule Ash.Type.CiString do if String.match?(value, regex) do errors else - [[message: "must match the pattern %{regex}", regex: inspect(regex)] | errors] + [ + [message: error_message("must match the pattern %{regex}"), regex: inspect(regex)] + | errors + ] end _, errors -> diff --git a/lib/ash/type/decimal.ex b/lib/ash/type/decimal.ex index f19e5d191..a52d15ae2 100644 --- a/lib/ash/type/decimal.ex +++ b/lib/ash/type/decimal.ex @@ -33,6 +33,7 @@ defmodule Ash.Type.Decimal do ] import Ash.Expr + import Ash.Gettext @moduledoc """ Represents a decimal. @@ -131,7 +132,7 @@ defmodule Ash.Type.Decimal do if ^expr > ^max do error( Ash.Error.Changes.InvalidChanges, - message: "must be less than or equal to %{max}", + message: ^error_message("must be less than or equal to %{max}"), vars: %{max: ^max} ) else @@ -144,7 +145,7 @@ defmodule Ash.Type.Decimal do if ^expr < ^min do error( Ash.Error.Changes.InvalidChanges, - message: "must be greater than or equal to %{min}", + message: ^error_message("must be greater than or equal to %{min}"), vars: %{min: ^min} ) else @@ -159,7 +160,7 @@ defmodule Ash.Type.Decimal do else error( Ash.Error.Changes.InvalidChanges, - message: "must be less than %{less_than}", + message: ^error_message("must be less than %{less_than}"), vars: %{less_than: ^less_than} ) end @@ -172,7 +173,7 @@ defmodule Ash.Type.Decimal do else error( Ash.Error.Changes.InvalidChanges, - message: "must be greater than %{greater_than}", + message: ^error_message("must be greater than %{greater_than}"), vars: %{greater_than: ^greater_than} ) end @@ -198,7 +199,7 @@ defmodule Ash.Type.Decimal do if count_significant_digits(value) > precision do [ [ - message: "must have no more than %{precision} significant digits", + message: error_message("must have no more than %{precision} significant digits"), precision: precision ] | errors @@ -214,7 +215,7 @@ defmodule Ash.Type.Decimal do if Decimal.scale(value) > scale do [ [ - message: "must have no more than %{scale} decimal places", + message: error_message("must have no more than %{scale} decimal places"), scale: scale ] | errors @@ -225,14 +226,17 @@ defmodule Ash.Type.Decimal do {:max, max}, errors -> if Decimal.compare(value, max) == :gt do - [[message: "must be less than or equal to %{max}", max: max] | errors] + [[message: error_message("must be less than or equal to %{max}"), max: max] | errors] else errors end {:min, min}, errors -> if Decimal.compare(value, min) == :lt do - [[message: "must be more than or equal to %{min}", min: min] | errors] + [ + [message: error_message("must be greater than or equal to %{min}"), min: min] + | errors + ] else errors end @@ -241,14 +245,23 @@ defmodule Ash.Type.Decimal do if Decimal.compare(value, less_than) == :lt do errors else - [[message: "must be less than %{less_than}", less_than: less_than] | errors] + [ + [message: error_message("must be less than %{less_than}"), less_than: less_than] + | errors + ] end {:greater_than, greater_than}, errors -> if Decimal.compare(value, greater_than) == :gt do errors else - [[message: "must be more than %{greater_than}", greater_than: greater_than] | errors] + [ + [ + message: error_message("must be greater than %{greater_than}"), + greater_than: greater_than + ] + | errors + ] end end) diff --git a/lib/ash/type/enum.ex b/lib/ash/type/enum.ex index 6ea3c830d..517bad2ac 100644 --- a/lib/ash/type/enum.ex +++ b/lib/ash/type/enum.ex @@ -157,6 +157,7 @@ defmodule Ash.Type.Enum do defmacro __using__(opts) do quote location: :keep, generated: true, bind_quoted: [opts: opts] do use Ash.Type + import Ash.Gettext require Ash.Expr @@ -277,7 +278,7 @@ defmodule Ash.Type.Enum do Ash.Expr.expr( error( Ash.Error.Changes.InvalidChanges, - message: "must be one of %{values}", + message: ^error_message("must be one of %{values}"), vars: %{values: ^Enum.join(@values, ", ")} ) ) @@ -302,7 +303,7 @@ defmodule Ash.Type.Enum do else error( Ash.Error.Changes.InvalidChanges, - message: "must be one of %{values}", + message: ^error_message("must be one of %{values}"), vars: %{values: ^Enum.join(@values, ", ")} ) end diff --git a/lib/ash/type/float.ex b/lib/ash/type/float.ex index d00699ebf..cbf87d723 100644 --- a/lib/ash/type/float.ex +++ b/lib/ash/type/float.ex @@ -23,6 +23,7 @@ defmodule Ash.Type.Float do ] import Ash.Expr + import Ash.Gettext @moduledoc """ Represents a float (floating point number) @@ -77,14 +78,17 @@ defmodule Ash.Type.Float do Enum.reduce(constraints, [], fn {:max, max}, errors -> if value > max do - [[message: "must be less than or equal to %{max}", max: max] | errors] + [[message: error_message("must be less than or equal to %{max}"), max: max] | errors] else errors end {:min, min}, errors -> if value < min do - [[message: "must be more than or equal to %{min}", min: min] | errors] + [ + [message: error_message("must be greater than or equal to %{min}"), min: min] + | errors + ] else errors end @@ -93,14 +97,23 @@ defmodule Ash.Type.Float do if value < less_than do errors else - [[message: "must be less than %{less_than}", less_than: less_than] | errors] + [ + [message: error_message("must be less than %{less_than}"), less_than: less_than] + | errors + ] end {:greater_than, greater_than}, errors -> if value > greater_than do errors else - [[message: "must be more than %{greater_than}", greater_than: greater_than] | errors] + [ + [ + message: error_message("must be greater than %{greater_than}"), + greater_than: greater_than + ] + | errors + ] end end) @@ -137,7 +150,7 @@ defmodule Ash.Type.Float do if ^expr > ^max do error( Ash.Error.Changes.InvalidChanges, - message: "must be less than or equal to %{max}", + message: ^error_message("must be less than or equal to %{max}"), vars: %{max: ^max} ) else @@ -150,7 +163,7 @@ defmodule Ash.Type.Float do if ^expr < ^min do error( Ash.Error.Changes.InvalidChanges, - message: "must be greater than or equal to %{min}", + message: ^error_message("must be greater than or equal to %{min}"), vars: %{min: ^min} ) else @@ -165,7 +178,7 @@ defmodule Ash.Type.Float do else error( Ash.Error.Changes.InvalidChanges, - message: "must be greater than %{less_than}", + message: ^error_message("must be less than %{less_than}"), vars: %{less_than: ^less_than} ) end @@ -178,7 +191,7 @@ defmodule Ash.Type.Float do else error( Ash.Error.Changes.InvalidChanges, - message: "must be greater than %{greater_than}", + message: ^error_message("must be greater than %{greater_than}"), vars: %{greater_than: ^greater_than} ) end diff --git a/lib/ash/type/function.ex b/lib/ash/type/function.ex index e89513ecd..521b81d18 100644 --- a/lib/ash/type/function.ex +++ b/lib/ash/type/function.ex @@ -24,6 +24,7 @@ defmodule Ash.Type.Function do """ use Ash.Type + import Ash.Gettext @impl true def storage_type(_), do: :binary @@ -34,7 +35,8 @@ defmodule Ash.Type.Function do @impl true def apply_constraints(term, constraints) do if constraints[:arity] && not is_function(term, constraints[:arity]) do - {:error, message: "Expected a function of arity %{arity}", arity: constraints[:arity]} + {:error, + message: error_message("Expected a function of arity %{arity}"), arity: constraints[:arity]} else {:ok, term} end diff --git a/lib/ash/type/integer.ex b/lib/ash/type/integer.ex index 815d02077..96a9c0544 100644 --- a/lib/ash/type/integer.ex +++ b/lib/ash/type/integer.ex @@ -23,6 +23,7 @@ defmodule Ash.Type.Integer do #{Spark.Options.docs(@constraints)} """ use Ash.Type + import Ash.Gettext require Ash.Expr @@ -48,7 +49,7 @@ defmodule Ash.Type.Integer do if ^expr > ^max do error( Ash.Error.Changes.InvalidChanges, - message: "must be less than or equal to %{max}", + message: ^error_message("must be less than or equal to %{max}"), vars: %{max: ^max} ) else @@ -61,7 +62,7 @@ defmodule Ash.Type.Integer do if ^expr < ^min do error( Ash.Error.Changes.InvalidChanges, - message: "must be greater than or equal to %{min}", + message: ^error_message("must be greater than or equal to %{min}"), vars: %{min: ^min} ) else @@ -75,14 +76,14 @@ defmodule Ash.Type.Integer do ^expr < ^min -> error( Ash.Error.Changes.InvalidChanges, - message: "must be greater than or equal to %{min}", + message: ^error_message("must be greater than or equal to %{min}"), vars: %{min: ^min} ) ^expr > ^max -> error( Ash.Error.Changes.InvalidChanges, - message: "must be less than or equal to %{max}", + message: ^error_message("must be less than or equal to %{max}"), vars: %{max: ^max} ) @@ -120,14 +121,17 @@ defmodule Ash.Type.Integer do Enum.reduce(constraints, [], fn {:max, max}, errors -> if value > max do - [[message: "must be less than or equal to %{max}", max: max] | errors] + [[message: error_message("must be less than or equal to %{max}"), max: max] | errors] else errors end {:min, min}, errors -> if value < min do - [[message: "must be more than or equal to %{min}", min: min] | errors] + [ + [message: error_message("must be greater than or equal to %{min}"), min: min] + | errors + ] else errors end diff --git a/lib/ash/type/keyword.ex b/lib/ash/type/keyword.ex index 201772208..0f704e51f 100644 --- a/lib/ash/type/keyword.ex +++ b/lib/ash/type/keyword.ex @@ -67,6 +67,7 @@ defmodule Ash.Type.Keyword do #{Spark.Options.docs(@constraints)} """ use Ash.Type + import Ash.Gettext @impl true def constraints, do: @constraints @@ -204,7 +205,7 @@ defmodule Ash.Type.Keyword do :error -> if field_constraints[:allow_nil?] == false do - field_error = [message: "field must be present", field: field] + field_error = [message: error_message("field must be present"), field: field] {errors_acc ++ [field_error], result_acc} else {errors_acc, result_acc} @@ -232,7 +233,7 @@ defmodule Ash.Type.Keyword do ) do {:ok, nil} -> if field_constraints[:allow_nil?] == false do - {:error, [[message: "value must not be nil", field: field]]} + {:error, [[message: error_message("value must not be nil"), field: field]]} else {:ok, [{field, nil} | result]} end @@ -252,7 +253,7 @@ defmodule Ash.Type.Keyword do {:error, [error]} :error -> - {:error, [[message: "invalid value", field: field]]} + {:error, [[message: error_message("invalid value"), field: field]]} end end diff --git a/lib/ash/type/map.ex b/lib/ash/type/map.ex index 5b36e5665..a1e8dfe20 100644 --- a/lib/ash/type/map.ex +++ b/lib/ash/type/map.ex @@ -80,6 +80,7 @@ defmodule Ash.Type.Map do #{Spark.Options.docs(@constraints)} """ use Ash.Type + import Ash.Gettext @impl true def constraints, do: @constraints @@ -256,7 +257,7 @@ defmodule Ash.Type.Map do :error -> if field_constraints[:allow_nil?] == false do - field_error = [message: "field must be present", field: field] + field_error = [message: error_message("field must be present"), field: field] {errors_acc ++ [field_error], result_acc} else {errors_acc, result_acc} @@ -284,7 +285,7 @@ defmodule Ash.Type.Map do ) do {:ok, nil} -> if field_constraints[:allow_nil?] == false do - {:error, [[message: "value must not be nil", field: field]]} + {:error, [[message: error_message("value must not be nil"), field: field]]} else {:ok, Map.put(result, field, nil)} end @@ -304,7 +305,7 @@ defmodule Ash.Type.Map do {:error, [error]} :error -> - {:error, [[message: "invalid value", field: field]]} + {:error, [[message: error_message("invalid value"), field: field]]} end end diff --git a/lib/ash/type/module.ex b/lib/ash/type/module.ex index 641e83793..c1d53fb3e 100644 --- a/lib/ash/type/module.ex +++ b/lib/ash/type/module.ex @@ -24,6 +24,7 @@ defmodule Ash.Type.Module do #{Spark.Options.docs(@constraints)} """ use Ash.Type + import Ash.Gettext @impl true def storage_type(_), do: :string @@ -61,7 +62,8 @@ defmodule Ash.Type.Module do else Enum.concat(errors, [ [ - message: "module %{module} does not implement the %{behaviour} behaviour", + message: + error_message("module %{module} does not implement the %{behaviour} behaviour"), module: module, behaviour: behaviour ] @@ -80,7 +82,7 @@ defmodule Ash.Type.Module do ArgumentError -> Enum.concat(errors, [ [ - message: "module %{module} does not implement the %{protocol} protocol", + message: error_message("module %{module} does not implement the %{protocol} protocol"), module: module, protocol: protocol ] diff --git a/lib/ash/type/new_type.ex b/lib/ash/type/new_type.ex index 70e374c3f..059f90798 100644 --- a/lib/ash/type/new_type.ex +++ b/lib/ash/type/new_type.ex @@ -139,6 +139,7 @@ defmodule Ash.Type.NewType do end use Ash.Type + import Ash.Gettext @behaviour Ash.Type.NewType @@ -222,7 +223,9 @@ defmodule Ash.Type.NewType do |> Enum.reduce_while({:ok, []}, fn {item, index}, {:ok, casted} -> case cast_input(item, constraints) do :error -> - {:halt, {:error, message: "invalid value at %{index}", index: index, path: [index]}} + {:halt, + {:error, + message: error_message("invalid value at %{index}"), index: index, path: [index]}} {:error, keyword} -> errors = diff --git a/lib/ash/type/string.ex b/lib/ash/type/string.ex index 385c6db6e..ce65b9712 100644 --- a/lib/ash/type/string.ex +++ b/lib/ash/type/string.ex @@ -41,6 +41,7 @@ defmodule Ash.Type.String do #{Spark.Options.docs(@constraints)} """ use Ash.Type + import Ash.Gettext require Ash.Expr @@ -102,7 +103,7 @@ defmodule Ash.Type.String do if string_length(^expr) > ^max do error( Ash.Error.Changes.InvalidChanges, - message: "length must be less than or equal to %{max}", + message: ^error_message("length must be less than or equal to %{max}"), vars: %{max: max} ) else @@ -115,7 +116,7 @@ defmodule Ash.Type.String do if string_length(^expr) < ^min do error( Ash.Error.Changes.InvalidChanges, - message: "length must be greater than or equal to %{min}", + message: ^error_message("length must be greater than or equal to %{min}"), vars: %{min: min} ) else @@ -129,14 +130,14 @@ defmodule Ash.Type.String do string_length(^expr) < ^min -> error( Ash.Error.Changes.InvalidChanges, - message: "length must be greater than or equal to %{min}", + message: ^error_message("length must be greater than or equal to %{min}"), vars: %{min: min} ) string_length(^expr) > ^max -> error( Ash.Error.Changes.InvalidChanges, - message: "length must be less than or equal to %{max}", + message: ^error_message("length must be less than or equal to %{max}"), vars: %{max: max} ) @@ -228,7 +229,13 @@ defmodule Ash.Type.String do Enum.reduce(constraints, [], fn {:max_length, max_length}, errors -> if String.length(value) > max_length do - [[message: "length must be less than or equal to %{max}", max: max_length] | errors] + [ + [ + message: error_message("length must be less than or equal to %{max}"), + max: max_length + ] + | errors + ] else errors end @@ -236,7 +243,10 @@ defmodule Ash.Type.String do {:min_length, min_length}, errors -> if String.length(value) < min_length do [ - [message: "length must be greater than or equal to %{min}", min: min_length] + [ + message: error_message("length must be greater than or equal to %{min}"), + min: min_length + ] | errors ] else @@ -256,7 +266,10 @@ defmodule Ash.Type.String do if Regex.match?(regex, value) do errors else - [[message: "must match the pattern %{regex}", regex: inspect(regex)] | errors] + [ + [message: error_message("must match the pattern %{regex}"), regex: inspect(regex)] + | errors + ] end _, errors -> diff --git a/lib/ash/type/struct.ex b/lib/ash/type/struct.ex index 14707d0ad..be3eb2f63 100644 --- a/lib/ash/type/struct.ex +++ b/lib/ash/type/struct.ex @@ -108,6 +108,7 @@ defmodule Ash.Type.Struct do """ use Ash.Type + import Ash.Gettext @impl true def constraints, do: @constraints @@ -384,7 +385,8 @@ defmodule Ash.Type.Struct do {:ok, casted} <- Ash.Type.apply_constraints(attribute.type, casted, attribute.constraints) do if is_nil(casted) and attribute.allow_nil? == false do - {:halt, {:error, field: attribute.name, message: "is required"}} + {:halt, + {:error, field: attribute.name, message: error_message("is required")}} else {:cont, {:ok, Map.put(record, attribute.name, casted)}} end @@ -398,7 +400,8 @@ defmodule Ash.Type.Struct do :error -> if attribute.allow_nil? == false do - {:halt, {:error, field: attribute.name, message: "is required"}} + {:halt, + {:error, field: attribute.name, message: error_message("is required")}} else {:cont, {:ok, record}} end @@ -433,7 +436,7 @@ defmodule Ash.Type.Struct do :error -> if field_constraints[:allow_nil?] == false do - field_error = [message: "field must be present", field: field] + field_error = [message: error_message("field must be present"), field: field] {errors_acc ++ [field_error], result_acc} else {errors_acc, result_acc} @@ -461,7 +464,7 @@ defmodule Ash.Type.Struct do ) do {:ok, nil} -> if field_constraints[:allow_nil?] == false do - {:error, [[message: "value must not be nil", field: field]]} + {:error, [[message: error_message("value must not be nil"), field: field]]} else {:ok, Map.put(result, field, nil)} end @@ -502,7 +505,7 @@ defmodule Ash.Type.Struct do {:error, error} :error -> - {:error, [[message: "invalid value", field: field]]} + {:error, [[message: error_message("invalid value"), field: field]]} end end diff --git a/lib/ash/type/tuple.ex b/lib/ash/type/tuple.ex index de985275c..a744b7c29 100644 --- a/lib/ash/type/tuple.ex +++ b/lib/ash/type/tuple.ex @@ -68,6 +68,7 @@ defmodule Ash.Type.Tuple do #{Spark.Options.docs(@constraints)} """ use Ash.Type + import Ash.Gettext @impl true def constraints, do: @constraints @@ -117,7 +118,7 @@ defmodule Ash.Type.Tuple do {:ok, value} else {:error, - message: "Expected %{expected_length} elements, got %{value_length}", + message: error_message("Expected %{expected_length} elements, got %{value_length}"), expected_length: field_length, value_length: value_length} end @@ -231,7 +232,7 @@ defmodule Ash.Type.Tuple do ) do {:ok, nil} -> if field_constraints[:allow_nil?] == false do - {:error, [[message: "value must not be nil", field: field]]} + {:error, [[message: error_message("value must not be nil"), field: field]]} else {:ok, [nil | acc]} end @@ -254,7 +255,7 @@ defmodule Ash.Type.Tuple do {:error, [error]} :error -> - {:error, [[message: "invalid value", field: field]]} + {:error, [[message: error_message("invalid value"), field: field]]} end end diff --git a/lib/ash/type/type.ex b/lib/ash/type/type.ex index 944b5d155..63cf7db2c 100644 --- a/lib/ash/type/type.ex +++ b/lib/ash/type/type.ex @@ -34,6 +34,7 @@ defmodule Ash.Type do ] alias Ash.Type.Registry + import Ash.Gettext @doc_array_constraints Keyword.put(@array_constraints, :items, type: :any, @@ -1240,7 +1241,7 @@ defmodule Ash.Type do if remove_nil_items? do {rest, errors} else - {[item | rest], [[message: "no nil values", index: index] | errors]} + {[item | rest], [[message: error_message("no nil values"), index: index] | errors]} end else {[item | rest], errors} @@ -1261,14 +1262,14 @@ defmodule Ash.Type do |> Enum.reduce([], fn {:min_length, min_length}, errors -> if length < min_length do - [message: "must have %{min} or more items", min: min_length] + [message: error_message("must have %{min} or more items"), min: min_length] else errors end {:max_length, max_length}, errors -> if length > max_length do - [message: "must have %{max} or fewer items", max: max_length] + [message: error_message("must have %{max} or fewer items"), max: max_length] else errors end @@ -1855,7 +1856,9 @@ defmodule Ash.Type do |> Enum.reduce_while({:ok, []}, fn {item, index}, {:ok, casted} -> case Ash.Type.cast_input(__MODULE__, item, single_constraints) do :error -> - {:halt, {:error, message: "invalid value at %{index}", index: index, path: [index]}} + {:halt, + {:error, + message: error_message("invalid value at %{index}"), index: index, path: [index]}} {:error, keyword} -> errors = diff --git a/priv/gettext/ash.pot b/priv/gettext/ash.pot index 654b62a65..e04e5ac19 100644 --- a/priv/gettext/ash.pot +++ b/priv/gettext/ash.pot @@ -13,178 +13,352 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Domain: ash\n" -#: lib/ash/resource/validation/action_is.ex:65 +#: lib/ash/type/tuple.ex:121 +msgid "Expected %{expected_length} elements, got %{value_length}" +msgstr "" + + +#: lib/ash/type/function.ex:38 +msgid "Expected a function of arity %{arity}" +msgstr "" + + +#: lib/ash/resource/change/cascade_destroy.ex:249 +#: lib/ash/resource/change/cascade_update.ex:181 +msgid "Relationship doesn't exist." +msgstr "" + + +#: lib/ash/resource/validation/action_is.ex:66 msgid "action must be one of %{action}" msgstr "" -#: lib/ash/resource/validation/present.ex:184 -#: lib/ash/resource/validation/present.ex:224 +#: lib/ash/resource/validation/present.ex:185 +#: lib/ash/resource/validation/present.ex:225 msgid "at least %{at_least} of %{keys} must be present" msgstr "" -#: lib/ash/resource/validation/present.ex:197 -#: lib/ash/resource/validation/present.ex:227 +#: lib/ash/resource/validation/present.ex:198 +#: lib/ash/resource/validation/present.ex:228 msgid "at most %{at_most} of %{keys} must be present" msgstr "" -#: lib/ash/resource/validation/confirm.ex:97 -#: lib/ash/resource/validation/confirm.ex:105 +#: lib/ash/type/atom.ex:59 +msgid "atom must be one of %{atom_list}, got: %{value}" +msgstr "" + + +#: lib/ash/changeset/changeset.ex:3495 +msgid "cannot be changed" +msgstr "" + + +#: lib/ash/changeset/changeset.ex:5940 +msgid "cannot manage a manual relationship" +msgstr "" + + +#: lib/ash/changeset/changeset.ex:6030 +msgid "cannot provide structs that don't match the destination" +msgstr "" + + +#: lib/ash/resource/validation/confirm.ex:98 +#: lib/ash/resource/validation/confirm.ex:106 msgid "confirmation did not match value" msgstr "" -#: lib/ash/resource/validation/string_length.ex:71 +#: lib/ash/resource/validation/string_length.ex:72 msgid "could not be parsed" msgstr "" -#: lib/ash/resource/validation/present.ex:140 -#: lib/ash/resource/validation/present.ex:221 +#: lib/ash/resource/change/relate_actor.ex:65 +msgid "could not relate to actor, as no actor was found (and :allow_nil? is false)" +msgstr "" + + +#: lib/ash/resource/validation/present.ex:141 +#: lib/ash/resource/validation/present.ex:222 msgid "exactly %{exactly} of %{keys} must be present" msgstr "" -#: lib/ash/resource/validation/data_one_of.ex:84 -#: lib/ash/resource/validation/data_one_of.ex:94 -#: lib/ash/resource/validation/one_of.ex:101 -#: lib/ash/resource/validation/one_of.ex:112 +#: lib/ash/resource/validation/data_one_of.ex:85 +#: lib/ash/resource/validation/data_one_of.ex:95 +#: lib/ash/resource/validation/one_of.ex:102 +#: lib/ash/resource/validation/one_of.ex:113 msgid "expected one of %{values}" msgstr "" -#: lib/ash/resource/validation/action_is.ex:70 +#: lib/ash/type/keyword.ex:208 +#: lib/ash/type/map.ex:260 +#: lib/ash/type/struct.ex:437 +msgid "field must be present" +msgstr "" + + +#: lib/ash/type/keyword.ex:256 +#: lib/ash/type/map.ex:308 +#: lib/ash/type/struct.ex:506 +#: lib/ash/type/tuple.ex:258 +msgid "invalid value" +msgstr "" + + +#: lib/ash/type/new_type.ex:226 +#: lib/ash/type/type.ex:1859 +msgid "invalid value at %{index}" +msgstr "" + + +#: lib/ash/type/struct.ex:388 +#: lib/ash/type/struct.ex:402 +msgid "is required" +msgstr "" + + +#: lib/ash/type/ci_string.ex:184 +#: lib/ash/type/string.ex:119 +#: lib/ash/type/string.ex:133 +#: lib/ash/type/string.ex:240 +msgid "length must be greater than or equal to %{min}" +msgstr "" + + +#: lib/ash/type/ci_string.ex:176 +#: lib/ash/type/string.ex:106 +#: lib/ash/type/string.ex:140 +#: lib/ash/type/string.ex:232 +msgid "length must be less than or equal to %{max}" +msgstr "" + + +#: lib/ash/type/module.ex:65 +msgid "module %{module} does not implement the %{behaviour} behaviour" +msgstr "" + + +#: lib/ash/type/module.ex:84 +msgid "module %{module} does not implement the %{protocol} protocol" +msgstr "" + + +#: lib/ash/resource/validation/action_is.ex:71 msgid "must be %{action}" msgstr "" -#: lib/ash/resource/validation/present.ex:134 -#: lib/ash/resource/validation/present.ex:212 +#: lib/ash/resource/validation/present.ex:135 +#: lib/ash/resource/validation/present.ex:213 msgid "must be absent" msgstr "" -#: lib/ash/resource/validation/changing.ex:172 -#: lib/ash/resource/validation/changing.ex:252 +#: lib/ash/resource/validation/changing.ex:173 +#: lib/ash/resource/validation/changing.ex:253 msgid "must be changing" msgstr "" -#: lib/ash/resource/validation/compare.ex:191 -#: lib/ash/resource/validation/compare.ex:417 +#: lib/ash/resource/validation/compare.ex:192 +#: lib/ash/resource/validation/compare.ex:418 msgid "must be equal to %{is_equal}" msgstr "" -#: lib/ash/resource/validation/compare.ex:139 -#: lib/ash/resource/validation/compare.ex:405 +#: lib/ash/resource/validation/compare.ex:140 +#: lib/ash/resource/validation/compare.ex:406 +#: lib/ash/type/decimal.ex:176 +#: lib/ash/type/decimal.ex:252 +#: lib/ash/type/float.ex:104 +#: lib/ash/type/float.ex:182 msgid "must be greater than %{greater_than}" msgstr "" -#: lib/ash/resource/validation/compare.ex:165 -#: lib/ash/resource/validation/compare.ex:411 +#: lib/ash/resource/validation/compare.ex:166 +#: lib/ash/resource/validation/compare.ex:412 msgid "must be greater than or equal to %{greater_than_or_equal_to}" msgstr "" -#: lib/ash/resource/validation/attribute_in.ex:74 -#: lib/ash/resource/validation/attribute_in.ex:83 +#: lib/ash/type/decimal.ex:148 +#: lib/ash/type/decimal.ex:236 +#: lib/ash/type/float.ex:88 +#: lib/ash/type/float.ex:154 +#: lib/ash/type/integer.ex:65 +#: lib/ash/type/integer.ex:79 +#: lib/ash/type/integer.ex:131 +msgid "must be greater than or equal to %{min}" +msgstr "" + + +#: lib/ash/resource/validation/attribute_in.ex:75 +#: lib/ash/resource/validation/attribute_in.ex:84 msgid "must be in %{list}" msgstr "" -#: lib/ash/resource/validation/pre_flight_authorization.ex:36 +#: lib/ash/resource/validation/pre_flight_authorization.ex:37 msgid "must be in a pre-flight authorization context" msgstr "" -#: lib/ash/resource/validation/compare.ex:151 -#: lib/ash/resource/validation/compare.ex:408 +#: lib/ash/resource/validation/compare.ex:152 +#: lib/ash/resource/validation/compare.ex:409 +#: lib/ash/type/decimal.ex:163 +#: lib/ash/type/decimal.ex:245 +#: lib/ash/type/float.ex:97 +#: lib/ash/type/float.ex:169 msgid "must be less than %{less_than}" msgstr "" -#: lib/ash/resource/validation/compare.ex:179 -#: lib/ash/resource/validation/compare.ex:414 +#: lib/ash/resource/validation/compare.ex:180 +#: lib/ash/resource/validation/compare.ex:415 msgid "must be less than or equal to %{less_than_or_equal_to}" msgstr "" -#: lib/ash/resource/validation/compare.ex:215 -#: lib/ash/resource/validation/compare.ex:423 +#: lib/ash/type/decimal.ex:135 +#: lib/ash/type/decimal.ex:229 +#: lib/ash/type/float.ex:81 +#: lib/ash/type/float.ex:141 +#: lib/ash/type/integer.ex:52 +#: lib/ash/type/integer.ex:86 +#: lib/ash/type/integer.ex:124 +msgid "must be less than or equal to %{max}" +msgstr "" + + +#: lib/ash/resource/validation/compare.ex:216 +#: lib/ash/resource/validation/compare.ex:424 msgid "must be nil" msgstr "" -#: lib/ash/resource/validation/present.ex:137 -#: lib/ash/resource/validation/present.ex:218 +#: lib/ash/type/enum.ex:281 +#: lib/ash/type/enum.ex:306 +msgid "must be one of %{values}" +msgstr "" + + +#: lib/ash/resource/validation/present.ex:138 +#: lib/ash/resource/validation/present.ex:219 msgid "must be present" msgstr "" -#: lib/ash/resource/validation/argument_equals.ex:70 -#: lib/ash/resource/validation/argument_in.ex:70 -#: lib/ash/resource/validation/attribute_equals.ex:46 -#: lib/ash/resource/validation/attribute_equals.ex:83 +#: lib/ash/resource/validation/argument_equals.ex:71 +#: lib/ash/resource/validation/argument_in.ex:71 +#: lib/ash/resource/validation/attribute_equals.ex:47 +#: lib/ash/resource/validation/attribute_equals.ex:84 msgid "must equal %{value}" msgstr "" -#: lib/ash/resource/validation/string_length.ex:112 -#: lib/ash/resource/validation/string_length.ex:207 +#: lib/ash/type/type.ex:1272 +msgid "must have %{max} or fewer items" +msgstr "" + + +#: lib/ash/type/type.ex:1265 +msgid "must have %{min} or more items" +msgstr "" + + +#: lib/ash/resource/validation/string_length.ex:113 +#: lib/ash/resource/validation/string_length.ex:208 msgid "must have length of at least %{min}" msgstr "" -#: lib/ash/resource/validation/string_length.ex:128 +#: lib/ash/resource/validation/string_length.ex:129 msgid "must have length of at most %{max}" msgstr "" -#: lib/ash/resource/validation/string_length.ex:202 +#: lib/ash/resource/validation/string_length.ex:203 msgid "must have length of between %{min} and %{max}" msgstr "" -#: lib/ash/resource/validation/string_length.ex:144 -#: lib/ash/resource/validation/string_length.ex:198 +#: lib/ash/resource/validation/string_length.ex:145 +#: lib/ash/resource/validation/string_length.ex:199 msgid "must have length of exactly %{exact}" msgstr "" -#: lib/ash/resource/validation/string_length.ex:210 +#: lib/ash/resource/validation/string_length.ex:211 msgid "must have length of no more than %{max}" msgstr "" -#: lib/ash/resource/validation/compare.ex:204 -#: lib/ash/resource/validation/compare.ex:420 +#: lib/ash/type/decimal.ex:202 +msgid "must have no more than %{precision} significant digits" +msgstr "" + + +#: lib/ash/type/decimal.ex:218 +msgid "must have no more than %{scale} decimal places" +msgstr "" + + +#: lib/ash/type/ci_string.ex:204 +#: lib/ash/type/string.ex:260 +msgid "must match the pattern %{regex}" +msgstr "" + + +#: lib/ash/resource/validation/compare.ex:205 +#: lib/ash/resource/validation/compare.ex:421 msgid "must not be equal to %{is_not_equal}" msgstr "" -#: lib/ash/resource/validation/compare.ex:226 -#: lib/ash/resource/validation/compare.ex:426 +#: lib/ash/resource/validation/compare.ex:227 +#: lib/ash/resource/validation/compare.ex:427 msgid "must not be nil" msgstr "" -#: lib/ash/resource/validation/present.ex:215 +#: lib/ash/resource/validation/present.ex:216 msgid "must not be present" msgstr "" -#: lib/ash/resource/validation/argument_does_not_equal.ex:71 -#: lib/ash/resource/validation/attribute_does_not_equal.ex:75 -#: lib/ash/resource/validation/attribute_does_not_equal.ex:84 +#: lib/ash/resource/validation/argument_does_not_equal.ex:72 +#: lib/ash/resource/validation/attribute_does_not_equal.ex:76 +#: lib/ash/resource/validation/attribute_does_not_equal.ex:85 msgid "must not equal %{value}" msgstr "" -#: lib/ash/resource/validation/function.ex:26 +#: lib/ash/resource/validation/function.ex:27 msgid "must pass function %{function}" msgstr "" + +#: lib/ash/type/type.ex:1244 +msgid "no nil values" +msgstr "" + + +#: lib/ash/changeset/changeset.ex:5931 +msgid "relationship is not editable" +msgstr "" + + +#: lib/ash/type/keyword.ex:236 +#: lib/ash/type/map.ex:288 +#: lib/ash/type/struct.ex:465 +#: lib/ash/type/tuple.ex:235 +msgid "value must not be nil" +msgstr "" + diff --git a/test/type/integer_test.exs b/test/type/integer_test.exs index ca3a1c07f..872b29754 100644 --- a/test/type/integer_test.exs +++ b/test/type/integer_test.exs @@ -32,7 +32,7 @@ defmodule Ash.Test.Type.IntegerTest do end test "invalid values" do - assert {:error, [[message: "must be more than or equal to %{min}", min: 2]]} = + assert {:error, [[message: "must be greater than or equal to %{min}", min: 2]]} = Ash.Type.Integer.apply_constraints(1, min: 2, max: 4) assert {:error, [[message: "must be less than or equal to %{max}", max: 4]]} = diff --git a/test/type/keyword_test.exs b/test/type/keyword_test.exs index 36e13dc83..1582718ed 100644 --- a/test/type/keyword_test.exs +++ b/test/type/keyword_test.exs @@ -127,7 +127,7 @@ defmodule Type.KeywordTest do assert [ %Ash.Error.Changes.InvalidAttribute{ field: :bar, - message: "must be more than or equal to %{min}", + message: "must be greater than or equal to %{min}", private_vars: nil, value: [foo: "hello", bar: -1], bread_crumbs: [], @@ -210,7 +210,7 @@ defmodule Type.KeywordTest do end) assert Enum.any?(errors, fn error -> - error.field == :bar && error.message == "must be more than or equal to %{min}" + error.field == :bar && error.message == "must be greater than or equal to %{min}" end) end @@ -270,7 +270,7 @@ defmodule Type.KeywordTest do # Check for age minimum error assert Enum.any?(errors, fn error -> - error.field == :age && String.contains?(error.message, "more than") + error.field == :age && String.contains?(error.message, "greater than") end) # Check for email format error @@ -339,7 +339,7 @@ defmodule Type.KeywordTest do # Check for positive integer constraint assert Enum.any?(errors, fn error -> - error.field == :positive_int && String.contains?(error.message, "more than") + error.field == :positive_int && String.contains?(error.message, "greater than") end) # Check for email format constraint @@ -370,7 +370,7 @@ defmodule Type.KeywordTest do |> Enum.map(&(&1[:message] || to_string(&1))) assert Enum.any?(error_messages, &String.contains?(&1, "must be present")) - assert Enum.any?(error_messages, &String.contains?(&1, "more than")) + assert Enum.any?(error_messages, &String.contains?(&1, "greater than")) {:ok, _} -> flunk("Expected validation errors but got success") @@ -404,7 +404,7 @@ defmodule Type.KeywordTest do assert Enum.any?(error_messages, &String.contains?(&1, "length")) # Check for count minimum constraint - assert Enum.any?(error_messages, &String.contains?(&1, "more than")) + assert Enum.any?(error_messages, &String.contains?(&1, "greater than")) # Check for email length constraint assert Enum.any?(error_messages, &String.contains?(&1, "length")) diff --git a/test/type/map_test.exs b/test/type/map_test.exs index 9460eae01..7c6c2357c 100644 --- a/test/type/map_test.exs +++ b/test/type/map_test.exs @@ -201,7 +201,7 @@ defmodule Ash.Type.MapTest do assert [ %Ash.Error.Changes.InvalidAttribute{ field: :integer_min_0, - message: "must be more than or equal to %{min}", + message: "must be greater than or equal to %{min}", private_vars: nil, value: %{integer_min_0: -1, foo: "hello"}, bread_crumbs: [], @@ -297,7 +297,7 @@ defmodule Ash.Type.MapTest do # Check that we have both errors assert Enum.any?(errors, fn error -> - error.field == :integer_min_0 && String.contains?(error.message, "more than") + error.field == :integer_min_0 && String.contains?(error.message, "greater than") end) assert Enum.any?(errors, fn error -> @@ -332,7 +332,7 @@ defmodule Ash.Type.MapTest do end) assert Enum.any?(errors, fn error -> - error.field == :integer_min_0 && String.contains?(error.message, "more than") + error.field == :integer_min_0 && String.contains?(error.message, "greater than") end) # We should also get the string length error @@ -368,7 +368,7 @@ defmodule Ash.Type.MapTest do # Check for integer minimum error assert Enum.any?(errors, fn error -> - error.field == :integer_min_0 && String.contains?(error.message, "more than") + error.field == :integer_min_0 && String.contains?(error.message, "greater than") end) # Check for string minimum length error @@ -410,7 +410,7 @@ defmodule Ash.Type.MapTest do |> Enum.map(&(&1[:message] || to_string(&1))) assert Enum.any?(error_messages, &String.contains?(&1, "must be present")) - assert Enum.any?(error_messages, &String.contains?(&1, "more than")) + assert Enum.any?(error_messages, &String.contains?(&1, "greater than")) assert Enum.any?(error_messages, &String.contains?(&1, "length")) {:ok, _} -> diff --git a/test/type/struct_test.exs b/test/type/struct_test.exs index ae2e5eb95..b2d4a1881 100644 --- a/test/type/struct_test.exs +++ b/test/type/struct_test.exs @@ -239,7 +239,7 @@ defmodule Type.StructTest do assert [ %Ash.Error.Changes.InvalidAttribute{ field: :bar, - message: "must be more than or equal to %{min}", + message: "must be greater than or equal to %{min}", private_vars: nil, value: %{bar: -1, foo: "hello"}, bread_crumbs: [], @@ -274,7 +274,7 @@ defmodule Type.StructTest do end) assert Enum.any?(errors, fn error -> - error.field == :bar && error.message == "must be more than or equal to %{min}" + error.field == :bar && error.message == "must be greater than or equal to %{min}" end) end @@ -344,7 +344,7 @@ defmodule Type.StructTest do # Check for age minimum error assert Enum.any?(errors, fn error -> - error.field == :age && String.contains?(error.message, "more than") + error.field == :age && String.contains?(error.message, "greater than") end) # Check for email format error @@ -376,7 +376,7 @@ defmodule Type.StructTest do |> Enum.map(&(&1[:message] || to_string(&1))) assert Enum.any?(error_messages, &String.contains?(&1, "must be present")) - assert Enum.any?(error_messages, &String.contains?(&1, "more than")) + assert Enum.any?(error_messages, &String.contains?(&1, "greater than")) {:ok, _} -> flunk("Expected validation errors but got success") diff --git a/test/type/tuple_test.exs b/test/type/tuple_test.exs index 557b27906..e297c3de1 100644 --- a/test/type/tuple_test.exs +++ b/test/type/tuple_test.exs @@ -120,7 +120,7 @@ defmodule Ash.Type.TupleTest do assert [ %Ash.Error.Changes.InvalidAttribute{ field: :integer_min_0, - message: "must be more than or equal to %{min}", + message: "must be greater than or equal to %{min}", private_vars: nil, value: {"hello", -1}, bread_crumbs: [],