-
-
Notifications
You must be signed in to change notification settings - Fork 1.7k
feat(lang): Added initial Thai locale #4230
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,5 +1,6 @@ | ||
| import az from "./locales/az.js"; | ||
| import en from "./locales/en.js"; | ||
| import es from "./locales/es.js"; | ||
| import th from "./locales/th.js"; | ||
|
|
||
| export { az, es, en }; | ||
| export { az, es, en, th }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,126 @@ | ||
| import type { $ZodStringFormats } from "../checks.js"; | ||
| import type * as errors from "../errors.js"; | ||
| import * as util from "../util.js"; | ||
|
|
||
| const Sizable: Record<string, { unit: string; verb: string }> = { | ||
| string: { unit: "ตัวอักษร", verb: "ควรมี" }, | ||
| file: { unit: "ไบต์", verb: "ควรมี" }, | ||
| array: { unit: "รายการ", verb: "ควรมี" }, | ||
| set: { unit: "รายการ", verb: "ควรมี" }, | ||
| }; | ||
|
|
||
| function getSizing(origin: string): { unit: string; verb: string } | null { | ||
| return Sizable[origin] ?? null; | ||
| } | ||
|
|
||
| export const parsedType = (data: any): string => { | ||
| const t = typeof data; | ||
|
|
||
| switch (t) { | ||
| case "number": { | ||
| return Number.isNaN(data) ? "ไม่ใช่ตัวเลข (NaN)" : "ตัวเลข"; | ||
| } | ||
| case "object": { | ||
| if (Array.isArray(data)) { | ||
| return "อาร์เรย์ (Array)"; | ||
| } | ||
| if (data === null) { | ||
| return "ไม่มีค่า (null)"; | ||
| } | ||
|
|
||
| if (Object.getPrototypeOf(data) !== Object.prototype && data.constructor) { | ||
| return data.constructor.name; | ||
| } | ||
| } | ||
| } | ||
| return t; | ||
| }; | ||
|
|
||
| const Nouns: { | ||
| [k in $ZodStringFormats | (string & {})]?: string; | ||
| } = { | ||
| regex: "ข้อมูลที่ป้อน", | ||
| email: "ที่อยู่อีเมล", | ||
| url: "URL", | ||
| emoji: "อิโมจิ", | ||
| uuid: "UUID", | ||
| uuidv4: "UUIDv4", | ||
| uuidv6: "UUIDv6", | ||
| nanoid: "nanoid", | ||
| guid: "GUID", | ||
| cuid: "cuid", | ||
| cuid2: "cuid2", | ||
| ulid: "ULID", | ||
| xid: "XID", | ||
| ksuid: "KSUID", | ||
| datetime: "วันที่เวลาแบบ ISO", | ||
| date: "วันที่แบบ ISO", | ||
| time: "เวลาแบบ ISO", | ||
| duration: "ช่วงเวลาแบบ ISO", | ||
| ipv4: "ที่อยู่ IPv4", | ||
| ipv6: "ที่อยู่ IPv6", | ||
| cidrv4: "ช่วง IP แบบ IPv4", | ||
| cidrv6: "ช่วง IP แบบ IPv6", | ||
| base64: "ข้อความแบบ Base64", | ||
| base64url: "ข้อความแบบ Base64 สำหรับ URL", | ||
| json_string: "ข้อความแบบ JSON", | ||
| e164: "เบอร์โทรศัพท์ระหว่างประเทศ (E.164)", | ||
| jwt: "โทเคน JWT", | ||
| template_literal: "ข้อมูลที่ป้อน", | ||
| }; | ||
|
|
||
| const error: errors.$ZodErrorMap = (issue) => { | ||
| switch (issue.code) { | ||
| case "invalid_type": | ||
| return `ประเภทข้อมูลไม่ถูกต้อง: ควรเป็น ${issue.expected} แต่ได้รับ ${parsedType(issue.input)}`; | ||
| case "invalid_value": | ||
| if (issue.values.length === 1) return `ค่าไม่ถูกต้อง: ควรเป็น ${util.stringifyPrimitive(issue.values[0])}`; | ||
| return `ตัวเลือกไม่ถูกต้อง: ควรเป็นหนึ่งใน ${util.joinValues(issue.values, "|")}`; | ||
| case "too_big": { | ||
| const adj = issue.inclusive ? "ไม่เกิน" : "น้อยกว่า"; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ตรงนี้ถ้าใช้ <= ตามต้นฉบับไปเลยจะชัดเจนกว่าไหมครับ
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ขอบคุณมากสำหรับคอมเมนต์ดี ๆ เลยครับ 🙏
ซึ่งผมตีความว่าเค้าต้องการให้พยายามแปลให้สุดเท่าที่ทำได้ครับ
โดยรวมผมแค่อยากให้ locale นี้ อิงกับการใช้ภาษาไทยแบบจริงจัง เท่าที่จะทำได้ แต่ถ้ามี feedback หรือทางเลือกอื่นที่ลื่นกว่านี้ ผมก็ยินดีมากเลยครับที่จะปรับปรุงต่อ 😊 |
||
| const sizing = getSizing(issue.origin); | ||
| if (sizing) | ||
| return `เกินกำหนด: ${issue.origin ?? "ค่า"} ควรมี${adj} ${issue.maximum.toString()} ${sizing.unit ?? "รายการ"}`; | ||
| return `เกินกำหนด: ${issue.origin ?? "ค่า"} ควรมี${adj} ${issue.maximum.toString()}`; | ||
| } | ||
| case "too_small": { | ||
| const adj = issue.inclusive ? "อย่างน้อย" : "มากกว่า"; | ||
| const sizing = getSizing(issue.origin); | ||
| if (sizing) { | ||
| return `น้อยกว่ากำหนด: ${issue.origin} ควรมี${adj} ${issue.minimum.toString()} ${sizing.unit}`; | ||
| } | ||
|
|
||
| return `น้อยกว่ากำหนด: ${issue.origin} ควรมี${adj} ${issue.minimum.toString()}`; | ||
| } | ||
| case "invalid_format": { | ||
| const _issue = issue as errors.$ZodStringFormatIssues; | ||
| if (_issue.format === "starts_with") { | ||
| return `รูปแบบไม่ถูกต้อง: ข้อความต้องขึ้นต้นด้วย "${_issue.prefix}"`; | ||
| } | ||
| if (_issue.format === "ends_with") return `รูปแบบไม่ถูกต้อง: ข้อความต้องลงท้ายด้วย "${_issue.suffix}"`; | ||
| if (_issue.format === "includes") return `รูปแบบไม่ถูกต้อง: ข้อความต้องมี "${_issue.includes}" อยู่ในข้อความ`; | ||
| if (_issue.format === "regex") return `รูปแบบไม่ถูกต้อง: ต้องตรงกับรูปแบบที่กำหนด ${_issue.pattern}`; | ||
| return `รูปแบบไม่ถูกต้อง: ${Nouns[_issue.format] ?? issue.format}`; | ||
| } | ||
| case "not_multiple_of": | ||
| return `ตัวเลขไม่ถูกต้อง: ต้องเป็นจำนวนที่หารด้วย ${issue.divisor} ได้ลงตัว`; | ||
| case "unrecognized_keys": | ||
| return `พบคีย์ที่ไม่รู้จัก: ${util.joinValues(issue.keys, ", ")}`; | ||
| case "invalid_key": | ||
| return `คีย์ไม่ถูกต้องใน ${issue.origin}`; | ||
| case "invalid_union": | ||
| return "ข้อมูลไม่ถูกต้อง: ไม่ตรงกับรูปแบบยูเนียนที่กำหนดไว้"; | ||
| case "invalid_element": | ||
| return `ข้อมูลไม่ถูกต้องใน ${issue.origin}`; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ผมว่าใช้ "องค์ประกอบไม่ถูกต้อง" หรือ "อีลีเมนต์ไม่ถูกต้อง" ก็ได้ครับ
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ดูจาก Test Cases การใช้งาน ผมคิดว่า คำว่า "ข้อมูลไม่ถูกต้องใน ..." น่าจะเหมาะสมกว่า แต่กว้างคลอบคลุมทุกบริบทกว่าคับ test("z.map invalid_element", () => {
const a = z.map(z.bigint(), z.number());
const r1 = z.safeParse(a, new Map([[BigInt(123), BigInt(123)]]));
expect(r1.error!.issues[0].code).toEqual("invalid_element");
expect(r1.error!.issues[0].path).toEqual([]);
});เพราะ "ข้อมูลบางชิ้นในโครงสร้าง" ที่ไม่ผ่านการตรวจสอบ เช่น "ข้อมูลไม่ถูกต้องใน map" ฟังดูเป็นกลาง ไม่สับสน ไม่แข็งเกินไป |
||
| default: | ||
| return `ข้อมูลไม่ถูกต้อง`; | ||
| } | ||
| }; | ||
|
|
||
| export { error }; | ||
|
|
||
| export default function (): { localeError: errors.$ZodErrorMap } { | ||
| return { | ||
| localeError: error, | ||
| }; | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -340,3 +340,4 @@ The following locales are available: | |
|
|
||
| - `az` — Azerbaijani | ||
| - `en` — English | ||
| - `th` — Thai | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ผมว่าแปลเป็น "เซต" เลยไหมดีครับ
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ผมคิดว่าในบริบทของภาษาอังกฤษ เค้านับ จำนวนสมาชิกในเซต มากกว่าตัวเซตเองนะครับ
อย่างในกรณีนี้:
ผมเลยเสนอให้ใช้คำว่า “รายการ” แทนคำว่า “เซต” เพื่อให้ตรงกับความหมายและไม่ทำให้สับสนครับ 🙏