From fff55ce681d227e73929c00aa0b2da94761954f0 Mon Sep 17 00:00:00 2001 From: Dobromir Yordanov <32433021+dobromiryor@users.noreply.github.com> Date: Wed, 3 Jan 2024 16:10:13 +0200 Subject: [PATCH] feat: add bulgarian translation --- .../with-next-i18next/next-i18next.config.js | 1 + examples/with-next-i18next/pages/index.tsx | 1 + .../public/locales/bg/common.json | 7 + .../public/locales/bg/zod.json | 112 +++++++++ packages/core/locales/bg/zod.json | 112 +++++++++ packages/core/tests/integrations/bg.test.ts | 217 ++++++++++++++++++ 6 files changed, 450 insertions(+) create mode 100644 examples/with-next-i18next/public/locales/bg/common.json create mode 100644 examples/with-next-i18next/public/locales/bg/zod.json create mode 100644 packages/core/locales/bg/zod.json create mode 100644 packages/core/tests/integrations/bg.test.ts diff --git a/examples/with-next-i18next/next-i18next.config.js b/examples/with-next-i18next/next-i18next.config.js index b6d5fda..58d0bfd 100644 --- a/examples/with-next-i18next/next-i18next.config.js +++ b/examples/with-next-i18next/next-i18next.config.js @@ -33,6 +33,7 @@ module.exports = { "fi", "cs", "id", + "bg", ], }, localePath: path.resolve("./public/locales"), diff --git a/examples/with-next-i18next/pages/index.tsx b/examples/with-next-i18next/pages/index.tsx index 28e5ba0..8cb2637 100644 --- a/examples/with-next-i18next/pages/index.tsx +++ b/examples/with-next-i18next/pages/index.tsx @@ -77,6 +77,7 @@ export default function HookForm() { > + diff --git a/examples/with-next-i18next/public/locales/bg/common.json b/examples/with-next-i18next/public/locales/bg/common.json new file mode 100644 index 0000000..94eb482 --- /dev/null +++ b/examples/with-next-i18next/public/locales/bg/common.json @@ -0,0 +1,7 @@ +{ + "username": "Потребителско име", + "username_placeholder": "Иван Иванов", + "email": "Имейл", + "favoriteNumber": "Любимо число", + "submit": "Изпрати" +} diff --git a/examples/with-next-i18next/public/locales/bg/zod.json b/examples/with-next-i18next/public/locales/bg/zod.json new file mode 100644 index 0000000..734cea0 --- /dev/null +++ b/examples/with-next-i18next/public/locales/bg/zod.json @@ -0,0 +1,112 @@ +{ + "errors": { + "invalid_type": "Очаквано - {{expected}}, получено - {{received}}", + "invalid_type_received_undefined": "Задължително поле", + "invalid_literal": "Невалиден литерал, очаквано {{expected}}", + "unrecognized_keys": "Неразпознат(и) ключ(ове) в обекта: {{- keys}}", + "invalid_union": "Невалидно обединение", + "invalid_union_discriminator": "Невалидна стойност на дискриминатора. Очаквано {{- options}}", + "invalid_enum_value": "Невалидна стойност на enum. Очаквано {{- options}}, получено '{{received}}'", + "invalid_arguments": "Невалидни аргументи на функцията", + "invalid_return_type": "Невалиден тип на върнатата от функцията стойност", + "invalid_date": "Невалидна дата", + "custom": "Невалидни данни", + "invalid_intersection_types": "Резултатите от сечението не могат да бъдат обединени", + "not_multiple_of": "Числото трябва да бъде кратно на {{multipleOf}}", + "not_finite": "Числото трябва да бъде крайно", + "invalid_string": { + "email": "Невалиден {{validation}}", + "url": "Невалиден {{validation}}", + "uuid": "Невалиден {{validation}}", + "cuid": "Невалиден {{validation}}", + "regex": "Невалиден {{validation}}", + "datetime": "Невалидна {{validation}}", + "startsWith": "Невалидни данни: трябва да започва с \"{{startsWith}}\"", + "endsWith": "Невалидни данни: трябва да завършва с \"{{endsWith}}\"" + }, + "too_small": { + "array": { + "exact": "Масивът трябва да съдържа точно {{minimum}} елемент(а)", + "inclusive": "Масивът трябва да съдържа поне {{minimum}} елемент(а)", + "not_inclusive": "Масивът трябва да съдържа повече от {{minimum}} елемент(а)" + }, + "string": { + "exact": "Низът трябва да съдържа точно {{minimum}} знак(а)", + "inclusive": "Низът трябва да съдържа поне {{minimum}} знак(а)", + "not_inclusive": "Низът трябва да съдържа повече от {{minimum}} знак(а)" + }, + "number": { + "exact": "Числото трябва да бъде точно {{minimum}}", + "inclusive": "Числото трябва да бъде по-голямо или равно на {{minimum}}", + "not_inclusive": "Числото трябва да бъде по-голямо от {{minimum}}" + }, + "set": { + "exact": "Невалидни данни", + "inclusive": "Невалидни данни", + "not_inclusive": "Невалидни данни" + }, + "date": { + "exact": "Датата трябва да бъде точно {{- minimum, datetime}}", + "inclusive": "Датата трябва да бъде по-голяма или равна на {{- minimum, datetime}}", + "not_inclusive": "Датата трябва да бъде по-голяма от {{- minimum, datetime}}" + } + }, + "too_big": { + "array": { + "exact": "Масивът трябва да съдържа точно {{maximum}} елемент(а)", + "inclusive": "Масивът трябва да съдържа най-много {{maximum}} елемент(а)", + "not_inclusive": "Масивът трябва да съдържа по-малко от {{maximum}} елемент(а)" + }, + "string": { + "exact": "Низът трябва да съдържа точно {{maximum}} знак(а)", + "inclusive": "Низът трябва да съдържа най-много {{maximum}} знак(а)", + "not_inclusive": "Низът трябва да съдържа по-малко от {{maximum}} знак(а)" + }, + "number": { + "exact": "Числото трябва да бъде точно {{maximum}}", + "inclusive": "Числото трябва да бъде по-малко или равно на {{maximum}}", + "not_inclusive": "Числото трябва да бъде по-малко от {{maximum}}" + }, + "set": { + "exact": "Невалидни данни", + "inclusive": "Невалидни данни", + "not_inclusive": "Невалидни данни" + }, + "date": { + "exact": "Датата трябва да бъде точно {{- maximum, datetime}}", + "inclusive": "Датата трябва да бъде по-малка или равна на {{- maximum, datetime}}", + "not_inclusive": "Датата трябва да бъде по-малка от {{- maximum, datetime}}" + } + } + }, + "validations": { + "email": "имейл", + "url": "URL", + "uuid": "UUID", + "cuid": "CUID", + "regex": "регулярен израз", + "datetime": "дата" + }, + "types": { + "function": "функция", + "number": "число", + "string": "низ", + "nan": "NaN", + "integer": "цяло число", + "float": "число с плаваща запетая", + "boolean": "булев тип", + "date": "дата", + "bigint": "bigint", + "undefined": "undefined", + "symbol": "символ", + "null": "null", + "array": "масив", + "object": "обект", + "unknown": "unknown", + "promise": "promise", + "void": "void", + "never": "never", + "map": "хеш таблица", + "set": "множество" + } +} diff --git a/packages/core/locales/bg/zod.json b/packages/core/locales/bg/zod.json new file mode 100644 index 0000000..734cea0 --- /dev/null +++ b/packages/core/locales/bg/zod.json @@ -0,0 +1,112 @@ +{ + "errors": { + "invalid_type": "Очаквано - {{expected}}, получено - {{received}}", + "invalid_type_received_undefined": "Задължително поле", + "invalid_literal": "Невалиден литерал, очаквано {{expected}}", + "unrecognized_keys": "Неразпознат(и) ключ(ове) в обекта: {{- keys}}", + "invalid_union": "Невалидно обединение", + "invalid_union_discriminator": "Невалидна стойност на дискриминатора. Очаквано {{- options}}", + "invalid_enum_value": "Невалидна стойност на enum. Очаквано {{- options}}, получено '{{received}}'", + "invalid_arguments": "Невалидни аргументи на функцията", + "invalid_return_type": "Невалиден тип на върнатата от функцията стойност", + "invalid_date": "Невалидна дата", + "custom": "Невалидни данни", + "invalid_intersection_types": "Резултатите от сечението не могат да бъдат обединени", + "not_multiple_of": "Числото трябва да бъде кратно на {{multipleOf}}", + "not_finite": "Числото трябва да бъде крайно", + "invalid_string": { + "email": "Невалиден {{validation}}", + "url": "Невалиден {{validation}}", + "uuid": "Невалиден {{validation}}", + "cuid": "Невалиден {{validation}}", + "regex": "Невалиден {{validation}}", + "datetime": "Невалидна {{validation}}", + "startsWith": "Невалидни данни: трябва да започва с \"{{startsWith}}\"", + "endsWith": "Невалидни данни: трябва да завършва с \"{{endsWith}}\"" + }, + "too_small": { + "array": { + "exact": "Масивът трябва да съдържа точно {{minimum}} елемент(а)", + "inclusive": "Масивът трябва да съдържа поне {{minimum}} елемент(а)", + "not_inclusive": "Масивът трябва да съдържа повече от {{minimum}} елемент(а)" + }, + "string": { + "exact": "Низът трябва да съдържа точно {{minimum}} знак(а)", + "inclusive": "Низът трябва да съдържа поне {{minimum}} знак(а)", + "not_inclusive": "Низът трябва да съдържа повече от {{minimum}} знак(а)" + }, + "number": { + "exact": "Числото трябва да бъде точно {{minimum}}", + "inclusive": "Числото трябва да бъде по-голямо или равно на {{minimum}}", + "not_inclusive": "Числото трябва да бъде по-голямо от {{minimum}}" + }, + "set": { + "exact": "Невалидни данни", + "inclusive": "Невалидни данни", + "not_inclusive": "Невалидни данни" + }, + "date": { + "exact": "Датата трябва да бъде точно {{- minimum, datetime}}", + "inclusive": "Датата трябва да бъде по-голяма или равна на {{- minimum, datetime}}", + "not_inclusive": "Датата трябва да бъде по-голяма от {{- minimum, datetime}}" + } + }, + "too_big": { + "array": { + "exact": "Масивът трябва да съдържа точно {{maximum}} елемент(а)", + "inclusive": "Масивът трябва да съдържа най-много {{maximum}} елемент(а)", + "not_inclusive": "Масивът трябва да съдържа по-малко от {{maximum}} елемент(а)" + }, + "string": { + "exact": "Низът трябва да съдържа точно {{maximum}} знак(а)", + "inclusive": "Низът трябва да съдържа най-много {{maximum}} знак(а)", + "not_inclusive": "Низът трябва да съдържа по-малко от {{maximum}} знак(а)" + }, + "number": { + "exact": "Числото трябва да бъде точно {{maximum}}", + "inclusive": "Числото трябва да бъде по-малко или равно на {{maximum}}", + "not_inclusive": "Числото трябва да бъде по-малко от {{maximum}}" + }, + "set": { + "exact": "Невалидни данни", + "inclusive": "Невалидни данни", + "not_inclusive": "Невалидни данни" + }, + "date": { + "exact": "Датата трябва да бъде точно {{- maximum, datetime}}", + "inclusive": "Датата трябва да бъде по-малка или равна на {{- maximum, datetime}}", + "not_inclusive": "Датата трябва да бъде по-малка от {{- maximum, datetime}}" + } + } + }, + "validations": { + "email": "имейл", + "url": "URL", + "uuid": "UUID", + "cuid": "CUID", + "regex": "регулярен израз", + "datetime": "дата" + }, + "types": { + "function": "функция", + "number": "число", + "string": "низ", + "nan": "NaN", + "integer": "цяло число", + "float": "число с плаваща запетая", + "boolean": "булев тип", + "date": "дата", + "bigint": "bigint", + "undefined": "undefined", + "symbol": "символ", + "null": "null", + "array": "масив", + "object": "обект", + "unknown": "unknown", + "promise": "promise", + "void": "void", + "never": "never", + "map": "хеш таблица", + "set": "множество" + } +} diff --git a/packages/core/tests/integrations/bg.test.ts b/packages/core/tests/integrations/bg.test.ts new file mode 100644 index 0000000..4c1ae70 --- /dev/null +++ b/packages/core/tests/integrations/bg.test.ts @@ -0,0 +1,217 @@ +import { beforeAll, expect, test } from "vitest"; +import { z } from "zod"; +import { getErrorMessage, getErrorMessageFromZodError, init } from "./helpers"; + +const LOCALE = "bg"; + +beforeAll(async () => { + await init(LOCALE); +}); + +test("string parser error messages", () => { + const schema = z.string(); + + expect(getErrorMessage(schema.safeParse(undefined))).toEqual( + "Задължително поле" + ); + expect(getErrorMessage(schema.safeParse(1))).toEqual( + "Очаквано - низ, получено - число" + ); + expect(getErrorMessage(schema.safeParse(true))).toEqual( + "Очаквано - низ, получено - булев тип" + ); + expect(getErrorMessage(schema.safeParse(Date))).toEqual( + "Очаквано - низ, получено - функция" + ); + expect(getErrorMessage(schema.safeParse(new Date()))).toEqual( + "Очаквано - низ, получено - дата" + ); + expect(getErrorMessage(schema.email().safeParse(""))).toEqual( + "Невалиден имейл" + ); + expect(getErrorMessage(schema.url().safeParse(""))).toEqual("Невалиден URL"); + expect(getErrorMessage(schema.regex(/aaa/).safeParse(""))).toEqual( + "Невалиден регулярен израз" + ); + expect(getErrorMessage(schema.startsWith("foo").safeParse(""))).toEqual( + 'Невалидни данни: трябва да започва с "foo"' + ); + expect(getErrorMessage(schema.endsWith("bar").safeParse(""))).toEqual( + 'Невалидни данни: трябва да завършва с "bar"' + ); + expect(getErrorMessage(schema.min(5).safeParse("a"))).toEqual( + "Низът трябва да съдържа поне 5 знак(а)" + ); + expect(getErrorMessage(schema.max(5).safeParse("abcdef"))).toEqual( + "Низът трябва да съдържа най-много 5 знак(а)" + ); + expect(getErrorMessage(schema.length(5).safeParse("abcdef"))).toEqual( + "Низът трябва да съдържа точно 5 знак(а)" + ); + expect( + getErrorMessage(schema.datetime().safeParse("2020-01-01T00:00:00+02:00")) + ).toEqual("Невалидна дата"); +}); + +test("number parser error messages", () => { + const schema = z.number(); + + expect(getErrorMessage(schema.safeParse(undefined))).toEqual( + "Задължително поле" + ); + expect(getErrorMessage(schema.safeParse(""))).toEqual( + "Очаквано - число, получено - низ" + ); + expect(getErrorMessage(schema.safeParse(null))).toEqual( + "Очаквано - число, получено - null" + ); + expect(getErrorMessage(schema.safeParse(NaN))).toEqual( + "Очаквано - число, получено - NaN" + ); + expect(getErrorMessage(schema.int().safeParse(0.1))).toEqual( + "Очаквано - цяло число, получено - число с плаваща запетая" + ); + expect(getErrorMessage(schema.multipleOf(5).safeParse(2))).toEqual( + "Числото трябва да бъде кратно на 5" + ); + expect(getErrorMessage(schema.step(0.1).safeParse(0.0001))).toEqual( + "Числото трябва да бъде кратно на 0.1" + ); + expect(getErrorMessage(schema.lt(5).safeParse(10))).toEqual( + "Числото трябва да бъде по-малко от 5" + ); + expect(getErrorMessage(schema.lte(5).safeParse(10))).toEqual( + "Числото трябва да бъде по-малко или равно на 5" + ); + expect(getErrorMessage(schema.gt(5).safeParse(1))).toEqual( + "Числото трябва да бъде по-голямо от 5" + ); + expect(getErrorMessage(schema.gte(5).safeParse(1))).toEqual( + "Числото трябва да бъде по-голямо или равно на 5" + ); + expect(getErrorMessage(schema.nonnegative().safeParse(-1))).toEqual( + "Числото трябва да бъде по-голямо или равно на 0" + ); + expect(getErrorMessage(schema.nonpositive().safeParse(1))).toEqual( + "Числото трябва да бъде по-малко или равно на 0" + ); + expect(getErrorMessage(schema.negative().safeParse(1))).toEqual( + "Числото трябва да бъде по-малко от 0" + ); + expect(getErrorMessage(schema.positive().safeParse(0))).toEqual( + "Числото трябва да бъде по-голямо от 0" + ); + expect(getErrorMessage(schema.finite().safeParse(Infinity))).toEqual( + "Числото трябва да бъде крайно" + ); +}); + +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( + "Очаквано - дата, получено - низ" + ); + expect( + getErrorMessage(schema.min(testDate).safeParse(new Date("2022-07-29"))) + ).toEqual( + `Датата трябва да бъде по-голяма или равна на ${testDate.toLocaleDateString( + LOCALE + )}` + ); + expect( + getErrorMessage(schema.max(testDate).safeParse(new Date("2022-08-02"))) + ).toEqual( + `Датата трябва да бъде по-малка или равна на ${testDate.toLocaleDateString( + LOCALE + )}` + ); + try { + await schema.parseAsync(new Date("invalid")); + } catch (err) { + expect((err as z.ZodError).issues[0].message).toEqual("Невалидна дата"); + } +}); + +test("array parser error messages", () => { + const schema = z.string().array(); + + expect(getErrorMessage(schema.safeParse(""))).toEqual( + "Очаквано - масив, получено - низ" + ); + expect(getErrorMessage(schema.min(5).safeParse([""]))).toEqual( + "Масивът трябва да съдържа поне 5 елемент(а)" + ); + expect(getErrorMessage(schema.max(2).safeParse(["", "", ""]))).toEqual( + "Масивът трябва да съдържа най-много 2 елемент(а)" + ); + expect(getErrorMessage(schema.nonempty().safeParse([]))).toEqual( + "Масивът трябва да съдържа поне 1 елемент(а)" + ); + expect(getErrorMessage(schema.length(2).safeParse([]))).toEqual( + "Масивът трябва да съдържа точно 2 елемент(а)" + ); +}); + +test("function parser error messages", () => { + const functionParse = z + .function(z.tuple([z.string()]), z.number()) + .parse((a: any) => a); + expect(getErrorMessageFromZodError(() => functionParse(""))).toEqual( + "Невалиден тип на върнатата от функцията стойност" + ); + expect(getErrorMessageFromZodError(() => functionParse(1 as any))).toEqual( + "Невалидни аргументи на функцията" + ); +}); + +test("other parser error messages", () => { + expect( + getErrorMessage( + z + .intersection( + z.number(), + z.number().transform((x) => x + 1) + ) + .safeParse(1234) + ) + ).toEqual("Резултатите от сечението не могат да бъдат обединени"); + expect(getErrorMessage(z.literal(12).safeParse(""))).toEqual( + "Невалиден литерал, очаквано 12" + ); + expect(getErrorMessage(z.enum(["A", "B", "C"]).safeParse("D"))).toEqual( + "Невалидна стойност на enum. Очаквано 'A' | 'B' | 'C', получено 'D'" + ); + expect( + getErrorMessage( + z + .object({ dog: z.string() }) + .strict() + .safeParse({ dog: "", cat: "", rat: "" }) + ) + ).toEqual("Неразпознат(и) ключ(ове) в обекта: '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("Невалидна стойност на дискриминатора. Очаквано 'a' | 'b'"); + expect( + getErrorMessage(z.union([z.string(), z.number()]).safeParse([true])) + ).toEqual("Невалидно обединение"); + expect( + getErrorMessage( + z + .string() + .refine(() => { + return false; + }) + .safeParse("") + ) + ).toEqual("Невалидни данни"); +});