diff --git a/examples/with-next-i18next/next-i18next.config.js b/examples/with-next-i18next/next-i18next.config.js
index 3898752..65f68b3 100644
--- a/examples/with-next-i18next/next-i18next.config.js
+++ b/examples/with-next-i18next/next-i18next.config.js
@@ -29,6 +29,7 @@ module.exports = {
"ro",
"uk-UA",
"uz",
+ "hr-HR",
"fi",
],
},
diff --git a/examples/with-next-i18next/pages/index.tsx b/examples/with-next-i18next/pages/index.tsx
index a48a7c8..9574225 100644
--- a/examples/with-next-i18next/pages/index.tsx
+++ b/examples/with-next-i18next/pages/index.tsx
@@ -83,6 +83,7 @@ export default function HookForm() {
+
diff --git a/examples/with-next-i18next/public/locales/hr-HR/common.json b/examples/with-next-i18next/public/locales/hr-HR/common.json
new file mode 100644
index 0000000..f6d56e7
--- /dev/null
+++ b/examples/with-next-i18next/public/locales/hr-HR/common.json
@@ -0,0 +1,7 @@
+{
+ "username": "Korisničko ime",
+ "username_placeholder": "Ivan Horvat",
+ "email": "Email",
+ "favoriteNumber": "Najdraži broj",
+ "submit": "Pošalji"
+}
diff --git a/examples/with-next-i18next/public/locales/hr-HR/zod.json b/examples/with-next-i18next/public/locales/hr-HR/zod.json
new file mode 100644
index 0000000..4b92a69
--- /dev/null
+++ b/examples/with-next-i18next/public/locales/hr-HR/zod.json
@@ -0,0 +1,112 @@
+{
+ "errors": {
+ "invalid_type": "Očekivano: {{expected}}, uneseno: {{received}}",
+ "invalid_type_received_undefined": "Obvezno polje",
+ "invalid_literal": "Neispravna literalna vrijednost, očekivano {{expected}}",
+ "unrecognized_keys": "Neprepoznat(i) ključ(evi) u objektu: {{- keys}}",
+ "invalid_union": "Neispravan unos",
+ "invalid_union_discriminator": "Neispravna vrijednost diskriminatora. Očekivano {{- options}}",
+ "invalid_enum_value": "Neispravna vrijednost enumeracije. Očekivano {{- options}}, uneseno '{{received}}'",
+ "invalid_arguments": "Neispravni argumenti funkcije",
+ "invalid_return_type": "Neispravan tip povratne vrijednosti",
+ "invalid_date": "Neispravan datum",
+ "custom": "Neispravan unos",
+ "invalid_intersection_types": "Rezultati presjecanja nisu se mogli spojiti",
+ "not_multiple_of": "Broj mora biti višekratnik od {{multipleOf}}",
+ "not_finite": "Broj mora biti konačan",
+ "invalid_string": {
+ "email": "Neispravan {{validation}}",
+ "url": "Neispravan {{validation}}",
+ "uuid": "Neispravan {{validation}}",
+ "cuid": "Neispravan {{validation}}",
+ "regex": "Neispravno",
+ "datetime": "Neispravan {{validation}}",
+ "startsWith": "Neispravan unos: mora započeti s \"{{startsWith}}\"",
+ "endsWith": "Neispravan unos: mora završiti s \"{{endsWith}}\""
+ },
+ "too_small": {
+ "array": {
+ "exact": "Niz mora sadržavati točno {{minimum}} element(a)",
+ "inclusive": "Niz mora sadržavati barem {{minimum}} element(a)",
+ "not_inclusive": "Niz mora sadržavati više od {{minimum}} element(a)"
+ },
+ "string": {
+ "exact": "Tekst mora sadržavati točno {{minimum}} znak(ova)",
+ "inclusive": "Tekst mora sadržavati barem {{minimum}} znak(ova)",
+ "not_inclusive": "Tekst mora sadržavati više od {{minimum}} znak(ova)"
+ },
+ "number": {
+ "exact": "Broj mora biti točno {{minimum}}",
+ "inclusive": "Broj mora biti veći od ili jednak {{minimum}}",
+ "not_inclusive": "Broj mora biti veći od {{minimum}}"
+ },
+ "set": {
+ "exact": "Neispravan unos",
+ "inclusive": "Neispravan unos",
+ "not_inclusive": "Neispravan unos"
+ },
+ "date": {
+ "exact": "Datum mora biti točno {{- minimum, datetime}}",
+ "inclusive": "Datum mora biti veći od ili jednak {{- minimum, datetime}}",
+ "not_inclusive": "Datum mora biti veći od {{- minimum, datetime}}"
+ }
+ },
+ "too_big": {
+ "array": {
+ "exact": "Niz mora sadržavati točno {{maximum}} element(a)",
+ "inclusive": "Niz mora sadržavati najviše {{maximum}} element(a)",
+ "not_inclusive": "Niz mora sadržavati manje od {{maximum}} element(a)"
+ },
+ "string": {
+ "exact": "Tekst mora sadržavati točno {{maximum}} znak(ova)",
+ "inclusive": "Tekst mora sadržavati najviše {{maximum}} znak(ova)",
+ "not_inclusive": "Tekst mora sadržavati manje od {{maximum}} znak(ova)"
+ },
+ "number": {
+ "exact": "Broj mora biti točno {{maximum}}",
+ "inclusive": "Broj mora biti manji od ili jednak {{maximum}}",
+ "not_inclusive": "Broj mora biti manji od {{maximum}}"
+ },
+ "set": {
+ "exact": "Neispravan unos",
+ "inclusive": "Neispravan unos",
+ "not_inclusive": "Neispravan unos"
+ },
+ "date": {
+ "exact": "Datum mora biti točno {{- maximum, datetime}}",
+ "inclusive": "Datum mora biti manji od ili jednak {{- maximum, datetime}}",
+ "not_inclusive": "Datum mora biti manji od {{- maximum, datetime}}"
+ }
+ }
+ },
+ "validations": {
+ "email": "email",
+ "url": "url",
+ "uuid": "uuid",
+ "cuid": "cuid",
+ "regex": "regex",
+ "datetime": "datum i vrijeme"
+ },
+ "types": {
+ "function": "funkcija",
+ "number": "broj",
+ "string": "tekst",
+ "nan": "nan",
+ "integer": "broj",
+ "float": "decimalni broj",
+ "boolean": "boolean",
+ "date": "datum",
+ "bigint": "broj",
+ "undefined": "nedefinirana vrijednost",
+ "symbol": "simbol",
+ "null": "null",
+ "array": "niz",
+ "object": "objekt",
+ "unknown": "nepoznato",
+ "promise": "promise",
+ "void": "void",
+ "never": "nikad",
+ "map": "mapa",
+ "set": "set"
+ }
+}
diff --git a/packages/core/locales/hr-HR/zod.json b/packages/core/locales/hr-HR/zod.json
new file mode 100644
index 0000000..4b92a69
--- /dev/null
+++ b/packages/core/locales/hr-HR/zod.json
@@ -0,0 +1,112 @@
+{
+ "errors": {
+ "invalid_type": "Očekivano: {{expected}}, uneseno: {{received}}",
+ "invalid_type_received_undefined": "Obvezno polje",
+ "invalid_literal": "Neispravna literalna vrijednost, očekivano {{expected}}",
+ "unrecognized_keys": "Neprepoznat(i) ključ(evi) u objektu: {{- keys}}",
+ "invalid_union": "Neispravan unos",
+ "invalid_union_discriminator": "Neispravna vrijednost diskriminatora. Očekivano {{- options}}",
+ "invalid_enum_value": "Neispravna vrijednost enumeracije. Očekivano {{- options}}, uneseno '{{received}}'",
+ "invalid_arguments": "Neispravni argumenti funkcije",
+ "invalid_return_type": "Neispravan tip povratne vrijednosti",
+ "invalid_date": "Neispravan datum",
+ "custom": "Neispravan unos",
+ "invalid_intersection_types": "Rezultati presjecanja nisu se mogli spojiti",
+ "not_multiple_of": "Broj mora biti višekratnik od {{multipleOf}}",
+ "not_finite": "Broj mora biti konačan",
+ "invalid_string": {
+ "email": "Neispravan {{validation}}",
+ "url": "Neispravan {{validation}}",
+ "uuid": "Neispravan {{validation}}",
+ "cuid": "Neispravan {{validation}}",
+ "regex": "Neispravno",
+ "datetime": "Neispravan {{validation}}",
+ "startsWith": "Neispravan unos: mora započeti s \"{{startsWith}}\"",
+ "endsWith": "Neispravan unos: mora završiti s \"{{endsWith}}\""
+ },
+ "too_small": {
+ "array": {
+ "exact": "Niz mora sadržavati točno {{minimum}} element(a)",
+ "inclusive": "Niz mora sadržavati barem {{minimum}} element(a)",
+ "not_inclusive": "Niz mora sadržavati više od {{minimum}} element(a)"
+ },
+ "string": {
+ "exact": "Tekst mora sadržavati točno {{minimum}} znak(ova)",
+ "inclusive": "Tekst mora sadržavati barem {{minimum}} znak(ova)",
+ "not_inclusive": "Tekst mora sadržavati više od {{minimum}} znak(ova)"
+ },
+ "number": {
+ "exact": "Broj mora biti točno {{minimum}}",
+ "inclusive": "Broj mora biti veći od ili jednak {{minimum}}",
+ "not_inclusive": "Broj mora biti veći od {{minimum}}"
+ },
+ "set": {
+ "exact": "Neispravan unos",
+ "inclusive": "Neispravan unos",
+ "not_inclusive": "Neispravan unos"
+ },
+ "date": {
+ "exact": "Datum mora biti točno {{- minimum, datetime}}",
+ "inclusive": "Datum mora biti veći od ili jednak {{- minimum, datetime}}",
+ "not_inclusive": "Datum mora biti veći od {{- minimum, datetime}}"
+ }
+ },
+ "too_big": {
+ "array": {
+ "exact": "Niz mora sadržavati točno {{maximum}} element(a)",
+ "inclusive": "Niz mora sadržavati najviše {{maximum}} element(a)",
+ "not_inclusive": "Niz mora sadržavati manje od {{maximum}} element(a)"
+ },
+ "string": {
+ "exact": "Tekst mora sadržavati točno {{maximum}} znak(ova)",
+ "inclusive": "Tekst mora sadržavati najviše {{maximum}} znak(ova)",
+ "not_inclusive": "Tekst mora sadržavati manje od {{maximum}} znak(ova)"
+ },
+ "number": {
+ "exact": "Broj mora biti točno {{maximum}}",
+ "inclusive": "Broj mora biti manji od ili jednak {{maximum}}",
+ "not_inclusive": "Broj mora biti manji od {{maximum}}"
+ },
+ "set": {
+ "exact": "Neispravan unos",
+ "inclusive": "Neispravan unos",
+ "not_inclusive": "Neispravan unos"
+ },
+ "date": {
+ "exact": "Datum mora biti točno {{- maximum, datetime}}",
+ "inclusive": "Datum mora biti manji od ili jednak {{- maximum, datetime}}",
+ "not_inclusive": "Datum mora biti manji od {{- maximum, datetime}}"
+ }
+ }
+ },
+ "validations": {
+ "email": "email",
+ "url": "url",
+ "uuid": "uuid",
+ "cuid": "cuid",
+ "regex": "regex",
+ "datetime": "datum i vrijeme"
+ },
+ "types": {
+ "function": "funkcija",
+ "number": "broj",
+ "string": "tekst",
+ "nan": "nan",
+ "integer": "broj",
+ "float": "decimalni broj",
+ "boolean": "boolean",
+ "date": "datum",
+ "bigint": "broj",
+ "undefined": "nedefinirana vrijednost",
+ "symbol": "simbol",
+ "null": "null",
+ "array": "niz",
+ "object": "objekt",
+ "unknown": "nepoznato",
+ "promise": "promise",
+ "void": "void",
+ "never": "nikad",
+ "map": "mapa",
+ "set": "set"
+ }
+}
diff --git a/packages/core/tests/integrations/hr-HR.test.ts b/packages/core/tests/integrations/hr-HR.test.ts
new file mode 100644
index 0000000..4c30e74
--- /dev/null
+++ b/packages/core/tests/integrations/hr-HR.test.ts
@@ -0,0 +1,209 @@
+import { test, expect, beforeAll } from "vitest";
+import { z } from "zod";
+import { init, getErrorMessage, getErrorMessageFromZodError } from "./helpers";
+
+const LOCALE = "hr-HR";
+
+beforeAll(async () => {
+ await init(LOCALE);
+});
+
+test("string parser error messages", () => {
+ const schema = z.string();
+
+ expect(getErrorMessage(schema.safeParse(undefined))).toEqual("Obvezno polje");
+ expect(getErrorMessage(schema.safeParse(1))).toEqual(
+ "Očekivano: tekst, uneseno: broj"
+ );
+ expect(getErrorMessage(schema.safeParse(true))).toEqual(
+ "Očekivano: tekst, uneseno: boolean"
+ );
+ expect(getErrorMessage(schema.safeParse(Date))).toEqual(
+ "Očekivano: tekst, uneseno: funkcija"
+ );
+ expect(getErrorMessage(schema.safeParse(new Date()))).toEqual(
+ "Očekivano: tekst, uneseno: datum"
+ );
+ expect(getErrorMessage(schema.email().safeParse(""))).toEqual(
+ "Neispravan email"
+ );
+ expect(getErrorMessage(schema.url().safeParse(""))).toEqual("Neispravan url");
+ expect(getErrorMessage(schema.regex(/aaa/).safeParse(""))).toEqual(
+ "Neispravno"
+ );
+ expect(getErrorMessage(schema.startsWith("foo").safeParse(""))).toEqual(
+ 'Neispravan unos: mora započeti s "foo"'
+ );
+ expect(getErrorMessage(schema.endsWith("bar").safeParse(""))).toEqual(
+ 'Neispravan unos: mora završiti s "bar"'
+ );
+ expect(getErrorMessage(schema.min(5).safeParse("a"))).toEqual(
+ "Tekst mora sadržavati barem 5 znak(ova)"
+ );
+ expect(getErrorMessage(schema.max(5).safeParse("abcdef"))).toEqual(
+ "Tekst mora sadržavati najviše 5 znak(ova)"
+ );
+ expect(getErrorMessage(schema.length(5).safeParse("abcdef"))).toEqual(
+ "Tekst mora sadržavati točno 5 znak(ova)"
+ );
+ expect(
+ getErrorMessage(schema.datetime().safeParse("2020-01-01T00:00:00+02:00"))
+ ).toEqual("Neispravan datum i vrijeme");
+});
+
+test("number parser error messages", () => {
+ const schema = z.number();
+
+ expect(getErrorMessage(schema.safeParse(undefined))).toEqual("Obvezno polje");
+ expect(getErrorMessage(schema.safeParse(""))).toEqual(
+ "Očekivano: broj, uneseno: tekst"
+ );
+ expect(getErrorMessage(schema.safeParse(null))).toEqual(
+ "Očekivano: broj, uneseno: null"
+ );
+ expect(getErrorMessage(schema.safeParse(NaN))).toEqual(
+ "Očekivano: broj, uneseno: nan"
+ );
+ expect(getErrorMessage(schema.int().safeParse(0.1))).toEqual(
+ "Očekivano: broj, uneseno: decimalni broj"
+ );
+ expect(getErrorMessage(schema.multipleOf(5).safeParse(2))).toEqual(
+ "Broj mora biti višekratnik od 5"
+ );
+ expect(getErrorMessage(schema.step(0.1).safeParse(0.0001))).toEqual(
+ "Broj mora biti višekratnik od 0.1"
+ );
+ expect(getErrorMessage(schema.lt(5).safeParse(10))).toEqual(
+ "Broj mora biti manji od 5"
+ );
+ expect(getErrorMessage(schema.lte(5).safeParse(10))).toEqual(
+ "Broj mora biti manji od ili jednak 5"
+ );
+ expect(getErrorMessage(schema.gt(5).safeParse(1))).toEqual(
+ "Broj mora biti veći od 5"
+ );
+ expect(getErrorMessage(schema.gte(5).safeParse(1))).toEqual(
+ "Broj mora biti veći od ili jednak 5"
+ );
+ expect(getErrorMessage(schema.nonnegative().safeParse(-1))).toEqual(
+ "Broj mora biti veći od ili jednak 0"
+ );
+ expect(getErrorMessage(schema.nonpositive().safeParse(1))).toEqual(
+ "Broj mora biti manji od ili jednak 0"
+ );
+ expect(getErrorMessage(schema.negative().safeParse(1))).toEqual(
+ "Broj mora biti manji od 0"
+ );
+ expect(getErrorMessage(schema.positive().safeParse(0))).toEqual(
+ "Broj mora biti veći od 0"
+ );
+ expect(getErrorMessage(schema.finite().safeParse(Infinity))).toEqual(
+ "Broj mora biti konačan"
+ );
+});
+
+test("date parser error messages", async () => {
+ const testDate = new Date("2022-08-01");
+ const schema = z.date();
+
+ expect(getErrorMessage(schema.safeParse("2022-12-01"))).toEqual(
+ "Očekivano: datum, uneseno: tekst"
+ );
+ expect(
+ getErrorMessage(schema.min(testDate).safeParse(new Date("2022-07-29")))
+ ).toEqual(
+ `Datum mora biti veći od ili jednak ${testDate.toLocaleDateString(LOCALE)}`
+ );
+ expect(
+ getErrorMessage(schema.max(testDate).safeParse(new Date("2022-08-02")))
+ ).toEqual(
+ `Datum mora biti manji od ili jednak ${testDate.toLocaleDateString(LOCALE)}`
+ );
+ try {
+ await schema.parseAsync(new Date("invalid"));
+ } catch (err) {
+ expect((err as z.ZodError).issues[0].message).toEqual("Neispravan datum");
+ }
+});
+
+test("array parser error messages", () => {
+ const schema = z.string().array();
+
+ expect(getErrorMessage(schema.safeParse(""))).toEqual(
+ "Očekivano: niz, uneseno: tekst"
+ );
+ expect(getErrorMessage(schema.min(5).safeParse([""]))).toEqual(
+ "Niz mora sadržavati barem 5 element(a)"
+ );
+ expect(getErrorMessage(schema.max(2).safeParse(["", "", ""]))).toEqual(
+ "Niz mora sadržavati najviše 2 element(a)"
+ );
+ expect(getErrorMessage(schema.nonempty().safeParse([]))).toEqual(
+ "Niz mora sadržavati barem 1 element(a)"
+ );
+ expect(getErrorMessage(schema.length(2).safeParse([]))).toEqual(
+ "Niz mora sadržavati točno 2 element(a)"
+ );
+});
+
+test("function parser error messages", () => {
+ const functionParse = z
+ .function(z.tuple([z.string()]), z.number())
+ .parse((a: any) => a);
+ expect(getErrorMessageFromZodError(() => functionParse(""))).toEqual(
+ "Neispravan tip povratne vrijednosti"
+ );
+ expect(getErrorMessageFromZodError(() => functionParse(1 as any))).toEqual(
+ "Neispravni argumenti funkcije"
+ );
+});
+
+test("other parser error messages", () => {
+ expect(
+ getErrorMessage(
+ z
+ .intersection(
+ z.number(),
+ z.number().transform((x) => x + 1)
+ )
+ .safeParse(1234)
+ )
+ ).toEqual("Rezultati presjecanja nisu se mogli spojiti");
+ expect(getErrorMessage(z.literal(12).safeParse(""))).toEqual(
+ "Neispravna literalna vrijednost, očekivano 12"
+ );
+ expect(getErrorMessage(z.enum(["A", "B", "C"]).safeParse("D"))).toEqual(
+ "Neispravna vrijednost enumeracije. Očekivano 'A' | 'B' | 'C', uneseno 'D'"
+ );
+ expect(
+ getErrorMessage(
+ z
+ .object({ dog: z.string() })
+ .strict()
+ .safeParse({ dog: "", cat: "", rat: "" })
+ )
+ ).toEqual("Neprepoznat(i) ključ(evi) u objektu: 'cat', 'rat'");
+ expect(
+ getErrorMessage(
+ z
+ .discriminatedUnion("type", [
+ z.object({ type: z.literal("a"), a: z.string() }),
+ z.object({ type: z.literal("b"), b: z.string() }),
+ ])
+ .safeParse({ type: "c", c: "abc" })
+ )
+ ).toEqual("Neispravna vrijednost diskriminatora. Očekivano 'a' | 'b'");
+ expect(
+ getErrorMessage(z.union([z.string(), z.number()]).safeParse([true]))
+ ).toEqual("Neispravan unos");
+ expect(
+ getErrorMessage(
+ z
+ .string()
+ .refine(() => {
+ return false;
+ })
+ .safeParse("")
+ )
+ ).toEqual("Neispravan unos");
+});