From dbc6f262ee02556a8d8ae4a37d116dbf3fb2831f Mon Sep 17 00:00:00 2001 From: umidullo Date: Tue, 5 Sep 2023 20:01:05 +0500 Subject: [PATCH 1/4] feat: add Uzbek language --- packages/core/locales/uz/zod.json | 112 ++++++++++ packages/core/tests/integrations/uz.test.ts | 217 ++++++++++++++++++++ 2 files changed, 329 insertions(+) create mode 100644 packages/core/locales/uz/zod.json create mode 100644 packages/core/tests/integrations/uz.test.ts diff --git a/packages/core/locales/uz/zod.json b/packages/core/locales/uz/zod.json new file mode 100644 index 0000000..e17e023 --- /dev/null +++ b/packages/core/locales/uz/zod.json @@ -0,0 +1,112 @@ +{ + "errors": { + "invalid_type": "Kutilayotgan tur - {{expected}}, qabul qilingan - {{received}}", + "invalid_type_received_undefined": "Majburiy maydon", + "invalid_literal": "Noto'g'ri so'zma-so'z qiymat, kutilmoqda {{expected}}", + "unrecognized_keys": "Obyektdagi kalit(lar) noto'g'ri: {{- keys}}", + "invalid_union": "Kesishma natijalarini birlashtirib bo'lmaydi", + "invalid_union_discriminator": "Diskriminator qiymati noto'g'ri. {{-options}} kutilmoqda", + "invalid_enum_value": "Enum qiymati noto'g'ri. Kutilayotgan {{-options}}, qabul qilingan '{{received}}'", + "invalid_arguments": "Funksiya argumentlari noto'g'ri", + "invalid_return_type": "Funktsiyani qaytarish turi noto'g'ri", + "invalid_date": "Sana noto'g'ri", + "custom": "Noto'g'ri kiritildi", + "invalid_intersection_types": "Kesishma natijalarini birlashtirib bo'lmaydi", + "not_multiple_of": "Son {{multipleOf}} ga karrali bo'lishi kerak", + "not_finite": "Son chekli bo'lishi kerak", + "invalid_string": { + "email": "Noto'g'ri {{validation}}", + "url": "Noto'g'ri {{validation}}", + "uuid": "Noto'g'ri {{validation}}", + "cuid": "Noto'g'ri {{validation}}", + "regex": "Noto'g'ri", + "datetime": "Noto'g'ri {{validation}}", + "startsWith": "Noto'g'ri kiritildi: \"{{startsWith}}\" bilan boshlanishi kerak", + "endsWith": "Noto'g'ri kiritildi: \"{{endsWith}}\" bilan tugashi kerak" + }, + "too_small": { + "array": { + "exact": "Massivda aynan {{minimum}} ta element(lar) bo'lishi kerak", + "inclusive": "Massivda kamida {{minimum}} ta element(lar) bo'lishi kerak", + "not_inclusive": "Massivda {{minimum}} ta dan ortiq element(lar) bo'lishi kerak" + }, + "string": { + "exact": "Satr aniq {{minimum}} ta belgidan iborat bo'lishi kerak", + "inclusive": "Satr kamida {{minimum}} belgidan iborat bo'lishi kerak", + "not_inclusive": "Satr {{minimum}} dan ortiq belgidan iborat bo'lishi kerak" + }, + "number": { + "exact": "Son aynan {{minimum}} bo'lishi kerak", + "inclusive": "Son {{minimum}} dan katta yoki unga teng bo'lishi kerak", + "not_inclusive": "Son {{minimum}} dan katta bo'lishi kerak" + }, + "set": { + "exact": "Noto'g'ri kiritildi", + "inclusive": "Noto'g'ri kiritildi", + "not_inclusive": "Noto'g'ri kiritildi" + }, + "date": { + "exact": "Sana aynan {{- minimum, sana vaqti}} bo'lishi kerak", + "inclusive": "Sana {{- minimum, datetime}} dan katta yoki unga teng bo'lishi kerak", + "not_inclusive": "Sana {{- minimum, datetime}} dan katta bo'lishi kerak" + } + }, + "too_big": { + "array": { + "exact": "Massivda aynan {{maximum}} ta element(lar) bo'lishi kerak", + "inclusive": "Massiv {{maximum}} ta elementdan oshmasligi kerak", + "not_inclusive": "Massiv {{maximum}} ta elementdan kam bo'lishi kerak" + }, + "string": { + "exact": "Satr aynan {{maximum}} ta belgidan iborat bo'lishi kerak", + "inclusive": "Satrda ko'pi bilan {{maximum}} ta belgi bo'lishi kerak", + "not_inclusive": "Satr {{maximum}} ta belgidan oshmasligi kerak" + }, + "number": { + "exact": "Son aynan {{maximum}} bo'lishi kerak", + "inclusive": "Son {{maximum}} dan kichik yoki unga teng bo'lishi kerak", + "not_inclusive": "Son {{maximum}} dan kichik bo'lishi kerak" + }, + "set": { + "exact": "Noto'g'ri kiritildi", + "inclusive": "Noto'g'ri kiritildi", + "not_inclusive": "Noto'g'ri kiritildi" + }, + "date": { + "exact": "Sana aynan {{- maximum, datetime}} bo'lishi kerak", + "inclusive": "Sana {{- maximum, datetime}} dan kichik yoki unga teng bo'lishi kerak", + "not_inclusive": "Sana {{- maximum, datetime}} dan kichik bo'lishi kerak" + } + } + }, + "validations": { + "email": "e-mail", + "url": "URL", + "uuid": "UUID", + "cuid": "CUID", + "regex": "muntazam ifoda", + "datetime": "sana va vaqt" + }, + "types": { + "function": "funksiya", + "number": "son", + "string": "satr", + "nan": "NaN", + "integer": "butun son", + "float": "suzuvchi nuqtali son", + "boolean": "mantiqiy qiymat", + "date": "sana", + "bigint": "bigint", + "undefined": "undefined", + "symbol": "belgi", + "null": "null", + "array": "massiv", + "object": "obyekt", + "unknown": "unknown", + "promise": "promise", + "void": "void", + "never": "never", + "map": "xesh jadvali", + "set": "to'plam" + } +} diff --git a/packages/core/tests/integrations/uz.test.ts b/packages/core/tests/integrations/uz.test.ts new file mode 100644 index 0000000..ca9c3cb --- /dev/null +++ b/packages/core/tests/integrations/uz.test.ts @@ -0,0 +1,217 @@ +import { test, expect, beforeAll } from "vitest"; +import { z } from "zod"; +import { init, getErrorMessage, getErrorMessageFromZodError } from "./helpers"; + +const LOCALE = "uz"; + +beforeAll(async () => { + await init(LOCALE); +}); + +test("string parser error messages", () => { + const schema = z.string(); + + expect(getErrorMessage(schema.safeParse(undefined))).toEqual( + "Majburiy maydon" + ); + expect(getErrorMessage(schema.safeParse(1))).toEqual( + "Kutilayotgan tur - satr, qabul qilingan - son" + ); + expect(getErrorMessage(schema.safeParse(true))).toEqual( + "Kutilayotgan tur - satr, qabul qilingan - mantiqiy qiymat" + ); + expect(getErrorMessage(schema.safeParse(Date))).toEqual( + "Kutilayotgan tur - satr, qabul qilingan - funksiya" + ); + expect(getErrorMessage(schema.safeParse(new Date()))).toEqual( + "Kutilayotgan tur - satr, qabul qilingan - sana" + ); + expect(getErrorMessage(schema.email().safeParse(""))).toEqual( + "Noto'g'ri e-mail" + ); + expect(getErrorMessage(schema.url().safeParse(""))).toEqual("Noto'g'ri URL"); + expect(getErrorMessage(schema.regex(/aaa/).safeParse(""))).toEqual( + "Noto'g'ri" + ); + expect(getErrorMessage(schema.startsWith("foo").safeParse(""))).toEqual( + "Noto'g'ri kiritildi: \"foo\" bilan boshlanishi kerak" + ); + expect(getErrorMessage(schema.endsWith("bar").safeParse(""))).toEqual( + "Noto'g'ri kiritildi: \"bar\" bilan tugashi kerak" + ); + expect(getErrorMessage(schema.min(5).safeParse("a"))).toEqual( + "Satr kamida 5 belgidan iborat bo'lishi kerak" + ); + expect(getErrorMessage(schema.max(5).safeParse("abcdef"))).toEqual( + "Satrda ko'pi bilan 5 ta belgi bo'lishi kerak" + ); + expect(getErrorMessage(schema.length(5).safeParse("abcdef"))).toEqual( + "Satr aynan 5 ta belgidan iborat bo'lishi kerak" + ); + expect( + getErrorMessage(schema.datetime().safeParse("2020-01-01T00:00:00+02:00")) + ).toEqual("Noto'g'ri sana va vaqt"); +}); + +test("number parser error messages", () => { + const schema = z.number(); + + expect(getErrorMessage(schema.safeParse(undefined))).toEqual( + "Majburiy maydon" + ); + expect(getErrorMessage(schema.safeParse(""))).toEqual( + "Kutilayotgan tur - son, qabul qilingan - satr" + ); + expect(getErrorMessage(schema.safeParse(null))).toEqual( + "Kutilayotgan tur - son, qabul qilingan - null" + ); + expect(getErrorMessage(schema.safeParse(NaN))).toEqual( + "Kutilayotgan tur - son, qabul qilingan - NaN" + ); + expect(getErrorMessage(schema.int().safeParse(0.1))).toEqual( + "Kutilayotgan tur - butun son, qabul qilingan - suzuvchi nuqtali son" + ); + expect(getErrorMessage(schema.multipleOf(5).safeParse(2))).toEqual( + "Son 5 ga karrali bo'lishi kerak" + ); + expect(getErrorMessage(schema.step(0.1).safeParse(0.0001))).toEqual( + "Son 0.1 ga karrali bo'lishi kerak" + ); + expect(getErrorMessage(schema.lt(5).safeParse(10))).toEqual( + "Son 5 dan kichik bo'lishi kerak" + ); + expect(getErrorMessage(schema.lte(5).safeParse(10))).toEqual( + "Son 5 dan kichik yoki unga teng bo'lishi kerak" + ); + expect(getErrorMessage(schema.gt(5).safeParse(1))).toEqual( + "Son 5 dan katta bo'lishi kerak" + ); + expect(getErrorMessage(schema.gte(5).safeParse(1))).toEqual( + "Son 5 dan katta yoki unga teng bo'lishi kerak" + ); + expect(getErrorMessage(schema.nonnegative().safeParse(-1))).toEqual( + "Son 0 dan katta yoki unga teng bo'lishi kerak" + ); + expect(getErrorMessage(schema.nonpositive().safeParse(1))).toEqual( + "Son 0 dan kichik yoki unga teng bo'lishi kerak" + ); + expect(getErrorMessage(schema.negative().safeParse(1))).toEqual( + "Son 0 dan kichik bo'lishi kerak" + ); + expect(getErrorMessage(schema.positive().safeParse(0))).toEqual( + "Son 0 dan katta bo'lishi kerak" + ); + expect(getErrorMessage(schema.finite().safeParse(Infinity))).toEqual( + "Son chekli bo'lishi kerak" + ); +}); + +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( + "Kutilayotgan tur - sana, qabul qilingan - satr" + ); + expect( + getErrorMessage(schema.min(testDate).safeParse(new Date("2022-07-29"))) + ).toEqual( + `Sana ${testDate.toLocaleDateString( + LOCALE + )} dan katta yoki unga teng bo'lishi kerak` + ); + expect( + getErrorMessage(schema.max(testDate).safeParse(new Date("2022-08-02"))) + ).toEqual( + `Sana ${testDate.toLocaleDateString( + LOCALE + )} dan kichik yoki unga teng bo'lishi kerak` + ); + try { + await schema.parseAsync(new Date("invalid")); + } catch (err) { + expect((err as z.ZodError).issues[0].message).toEqual("Sana noto'g'ri"); + } +}); + +test("array parser error messages", () => { + const schema = z.string().array(); + + expect(getErrorMessage(schema.safeParse(""))).toEqual( + "Kutilayotgan tur - massiv, qabul qilingan - satr" + ); + expect(getErrorMessage(schema.min(5).safeParse([""]))).toEqual( + "Massivda kamida 5 ta element(lar) bo'lishi kerak" + ); + expect(getErrorMessage(schema.max(2).safeParse(["", "", ""]))).toEqual( + "Massiv 2 ta elementdan oshmasligi kerak" + ); + expect(getErrorMessage(schema.nonempty().safeParse([]))).toEqual( + "Massivda kamida 1 ta element(lar) bo'lishi kerak" + ); + expect(getErrorMessage(schema.length(2).safeParse([]))).toEqual( + "Massivda aynan 2 ta element(lar) bo'lishi kerak" + ); +}); + +test("function parser error messages", () => { + const functionParse = z + .function(z.tuple([z.string()]), z.number()) + .parse((a: any) => a); + expect(getErrorMessageFromZodError(() => functionParse(""))).toEqual( + "Funktsiyani qaytarish turi noto'g'ri" + ); + expect(getErrorMessageFromZodError(() => functionParse(1 as any))).toEqual( + "Funksiya argumentlari noto'g'ri" + ); +}); + +test("other parser error messages", () => { + expect( + getErrorMessage( + z + .intersection( + z.number(), + z.number().transform((x) => x + 1) + ) + .safeParse(1234) + ) + ).toEqual("Kesishma natijalarini birlashtirib bo'lmaydi"); + expect(getErrorMessage(z.literal(12).safeParse(""))).toEqual( + "Noto'g'ri so'zma-so'z qiymat, kutilmoqda 12" + ); + expect(getErrorMessage(z.enum(["A", "B", "C"]).safeParse("D"))).toEqual( + "Enum qiymati noto'g'ri. Kutilayotgan 'A' | 'B' | 'C', qabul qilingan 'D'" + ); + expect( + getErrorMessage( + z + .object({ dog: z.string() }) + .strict() + .safeParse({ dog: "", cat: "", rat: "" }) + ) + ).toEqual("Obyektdagi kalit(lar) noto'g'ri: '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("Diskriminator qiymati noto'g'ri. 'a' | 'b' kutilmoqda"); + expect( + getErrorMessage(z.union([z.string(), z.number()]).safeParse([true])) + ).toEqual("Kesishma natijalarini birlashtirib bo'lmaydi"); + expect( + getErrorMessage( + z + .string() + .refine(() => { + return false; + }) + .safeParse("") + ) + ).toEqual("Noto'g'ri kiritildi"); +}); From 9f783755ed0c5f2fdc5662ecef3a34fe7220ce3e Mon Sep 17 00:00:00 2001 From: umidullo Date: Tue, 5 Sep 2023 20:26:30 +0500 Subject: [PATCH 2/4] feat: add examples --- .../with-next-i18next/next-i18next.config.js | 1 + examples/with-next-i18next/pages/index.tsx | 1 + .../public/locales/uz/common.json | 7 ++ .../public/locales/uz/zod.json | 112 ++++++++++++++++++ 4 files changed, 121 insertions(+) create mode 100644 examples/with-next-i18next/public/locales/uz/common.json create mode 100644 examples/with-next-i18next/public/locales/uz/zod.json diff --git a/examples/with-next-i18next/next-i18next.config.js b/examples/with-next-i18next/next-i18next.config.js index 4392c87..0d01f7f 100644 --- a/examples/with-next-i18next/next-i18next.config.js +++ b/examples/with-next-i18next/next-i18next.config.js @@ -27,6 +27,7 @@ module.exports = { "ru", "ro", "uk-UA", + "uz", ], }, localePath: path.resolve("./public/locales"), diff --git a/examples/with-next-i18next/pages/index.tsx b/examples/with-next-i18next/pages/index.tsx index e1b28b3..336ebed 100644 --- a/examples/with-next-i18next/pages/index.tsx +++ b/examples/with-next-i18next/pages/index.tsx @@ -92,6 +92,7 @@ export default function HookForm() { + diff --git a/examples/with-next-i18next/public/locales/uz/common.json b/examples/with-next-i18next/public/locales/uz/common.json new file mode 100644 index 0000000..197fd27 --- /dev/null +++ b/examples/with-next-i18next/public/locales/uz/common.json @@ -0,0 +1,7 @@ +{ + "username": "Foydalanuvchining ismi", + "username_placeholder": "John Doe", + "email": "Email", + "favoriteNumber": "Sevimli raqam", + "submit": "Yuborish" +} diff --git a/examples/with-next-i18next/public/locales/uz/zod.json b/examples/with-next-i18next/public/locales/uz/zod.json new file mode 100644 index 0000000..e17e023 --- /dev/null +++ b/examples/with-next-i18next/public/locales/uz/zod.json @@ -0,0 +1,112 @@ +{ + "errors": { + "invalid_type": "Kutilayotgan tur - {{expected}}, qabul qilingan - {{received}}", + "invalid_type_received_undefined": "Majburiy maydon", + "invalid_literal": "Noto'g'ri so'zma-so'z qiymat, kutilmoqda {{expected}}", + "unrecognized_keys": "Obyektdagi kalit(lar) noto'g'ri: {{- keys}}", + "invalid_union": "Kesishma natijalarini birlashtirib bo'lmaydi", + "invalid_union_discriminator": "Diskriminator qiymati noto'g'ri. {{-options}} kutilmoqda", + "invalid_enum_value": "Enum qiymati noto'g'ri. Kutilayotgan {{-options}}, qabul qilingan '{{received}}'", + "invalid_arguments": "Funksiya argumentlari noto'g'ri", + "invalid_return_type": "Funktsiyani qaytarish turi noto'g'ri", + "invalid_date": "Sana noto'g'ri", + "custom": "Noto'g'ri kiritildi", + "invalid_intersection_types": "Kesishma natijalarini birlashtirib bo'lmaydi", + "not_multiple_of": "Son {{multipleOf}} ga karrali bo'lishi kerak", + "not_finite": "Son chekli bo'lishi kerak", + "invalid_string": { + "email": "Noto'g'ri {{validation}}", + "url": "Noto'g'ri {{validation}}", + "uuid": "Noto'g'ri {{validation}}", + "cuid": "Noto'g'ri {{validation}}", + "regex": "Noto'g'ri", + "datetime": "Noto'g'ri {{validation}}", + "startsWith": "Noto'g'ri kiritildi: \"{{startsWith}}\" bilan boshlanishi kerak", + "endsWith": "Noto'g'ri kiritildi: \"{{endsWith}}\" bilan tugashi kerak" + }, + "too_small": { + "array": { + "exact": "Massivda aynan {{minimum}} ta element(lar) bo'lishi kerak", + "inclusive": "Massivda kamida {{minimum}} ta element(lar) bo'lishi kerak", + "not_inclusive": "Massivda {{minimum}} ta dan ortiq element(lar) bo'lishi kerak" + }, + "string": { + "exact": "Satr aniq {{minimum}} ta belgidan iborat bo'lishi kerak", + "inclusive": "Satr kamida {{minimum}} belgidan iborat bo'lishi kerak", + "not_inclusive": "Satr {{minimum}} dan ortiq belgidan iborat bo'lishi kerak" + }, + "number": { + "exact": "Son aynan {{minimum}} bo'lishi kerak", + "inclusive": "Son {{minimum}} dan katta yoki unga teng bo'lishi kerak", + "not_inclusive": "Son {{minimum}} dan katta bo'lishi kerak" + }, + "set": { + "exact": "Noto'g'ri kiritildi", + "inclusive": "Noto'g'ri kiritildi", + "not_inclusive": "Noto'g'ri kiritildi" + }, + "date": { + "exact": "Sana aynan {{- minimum, sana vaqti}} bo'lishi kerak", + "inclusive": "Sana {{- minimum, datetime}} dan katta yoki unga teng bo'lishi kerak", + "not_inclusive": "Sana {{- minimum, datetime}} dan katta bo'lishi kerak" + } + }, + "too_big": { + "array": { + "exact": "Massivda aynan {{maximum}} ta element(lar) bo'lishi kerak", + "inclusive": "Massiv {{maximum}} ta elementdan oshmasligi kerak", + "not_inclusive": "Massiv {{maximum}} ta elementdan kam bo'lishi kerak" + }, + "string": { + "exact": "Satr aynan {{maximum}} ta belgidan iborat bo'lishi kerak", + "inclusive": "Satrda ko'pi bilan {{maximum}} ta belgi bo'lishi kerak", + "not_inclusive": "Satr {{maximum}} ta belgidan oshmasligi kerak" + }, + "number": { + "exact": "Son aynan {{maximum}} bo'lishi kerak", + "inclusive": "Son {{maximum}} dan kichik yoki unga teng bo'lishi kerak", + "not_inclusive": "Son {{maximum}} dan kichik bo'lishi kerak" + }, + "set": { + "exact": "Noto'g'ri kiritildi", + "inclusive": "Noto'g'ri kiritildi", + "not_inclusive": "Noto'g'ri kiritildi" + }, + "date": { + "exact": "Sana aynan {{- maximum, datetime}} bo'lishi kerak", + "inclusive": "Sana {{- maximum, datetime}} dan kichik yoki unga teng bo'lishi kerak", + "not_inclusive": "Sana {{- maximum, datetime}} dan kichik bo'lishi kerak" + } + } + }, + "validations": { + "email": "e-mail", + "url": "URL", + "uuid": "UUID", + "cuid": "CUID", + "regex": "muntazam ifoda", + "datetime": "sana va vaqt" + }, + "types": { + "function": "funksiya", + "number": "son", + "string": "satr", + "nan": "NaN", + "integer": "butun son", + "float": "suzuvchi nuqtali son", + "boolean": "mantiqiy qiymat", + "date": "sana", + "bigint": "bigint", + "undefined": "undefined", + "symbol": "belgi", + "null": "null", + "array": "massiv", + "object": "obyekt", + "unknown": "unknown", + "promise": "promise", + "void": "void", + "never": "never", + "map": "xesh jadvali", + "set": "to'plam" + } +} From ec52291fabea33ad7843091b35ccb9ffd064777d Mon Sep 17 00:00:00 2001 From: umidullo Date: Tue, 5 Sep 2023 20:28:54 +0500 Subject: [PATCH 3/4] fix: option title translation --- examples/with-next-i18next/pages/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/with-next-i18next/pages/index.tsx b/examples/with-next-i18next/pages/index.tsx index 336ebed..f966bfc 100644 --- a/examples/with-next-i18next/pages/index.tsx +++ b/examples/with-next-i18next/pages/index.tsx @@ -92,7 +92,7 @@ export default function HookForm() { - + From cd4f3ec00f3fa22df7442069ce37a4c1e4c5600c Mon Sep 17 00:00:00 2001 From: umidullo Date: Tue, 5 Sep 2023 20:34:58 +0500 Subject: [PATCH 4/4] fix: option title typo --- examples/with-next-i18next/pages/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/with-next-i18next/pages/index.tsx b/examples/with-next-i18next/pages/index.tsx index f966bfc..5fabf25 100644 --- a/examples/with-next-i18next/pages/index.tsx +++ b/examples/with-next-i18next/pages/index.tsx @@ -92,7 +92,7 @@ export default function HookForm() { - +