แปลข้อความที่สมบูรณ์
ด้วย t-string ของ Python¶
gettext-tstrings เชื่อม t-string ของ Python 3.14 ขึ้นไปเข้ากับแคตตาล็อก
gettext มาตรฐานและเครื่องมือของ Babel ค่าและการจัดรูปแบบยังคงอยู่ในโค้ดแอปพลิเคชัน
ส่วนนักแปลทำงานกับข้อความที่สมบูรณ์และตัวยึดตำแหน่ง {name} เรียบง่าย:
import gettext
from gettext_tstrings import Translator
_ = Translator(gettext.translation("messages", localedir="locales"))
name = "Ada"
print(_(t"Hello {name}")) # with a Japanese catalog: こんにちは Ada
แคตตาล็อกบรรจุ Hello {name} คำแปลอาจย้ายที่หรือใช้ {name} ซ้ำได้
แต่ถ้ามันตัดตัวยึดตำแหน่งทิ้ง เปลี่ยนชื่อ หรือเปลี่ยนการจัดรูปแบบของมัน
การตรวจสอบแคตตาล็อกจะรายงานข้อผิดพลาดนั้น และหากรายการที่ไม่ถูกต้อง
ยังหลุดไปถึงระบบจริงจนได้ ไลบรารีจะบันทึกคำเตือน
แล้วเรนเดอร์ข้อความต้นทางแทนที่จะแครช
เริ่มบทแนะนำห้านาที เทียบกับทางเลือกอื่น
อัลฟา · Python 3.14 ขึ้นไป · แคตตาล็อก PO/MO มาตรฐาน · ไม่มี dependency ตอนรันไทม์จากภายนอก
เว็บไซต์นี้ปฏิบัติจริงตามสิ่งที่ตัวเองสอน: เอกสารทุกภาษา —
ทั้งเมนูนำทาง ป้ายกำกับ และรายงานการ build ที่รองรับรูปพหูพจน์ —
ล้วนถูกเรนเดอร์จากแคตตาล็อก PO ด้วย
gettext-tstrings เอง
นี่เหมาะกับคุณหรือไม่¶
เหมาะแล้วในวันนี้ ถ้า แอปพลิเคชันของคุณรันบน Python 3.14 ขึ้นไป คุณใช้ gettext และ Babel อยู่แล้วหรืออยากรับเวิร์กโฟลว์ PO/MO ของมันมาใช้ และคุณต้องการไวยากรณ์ t-string ที่มีตัวยึดตำแหน่งแบบมีชื่อซึ่งถูกตรวจสอบก่อนเรนเดอร์
ยังไม่เหมาะ ถ้า คุณต้องใช้ Python 3.13 หรือเก่ากว่า คุณต้องการ Python API ที่เสถียร — นี่ยังเป็นรุ่นอัลฟา และข้อกำหนดคือส่วนของมันที่นิ่งแล้ว — หรือข้อความที่ต้องแปลของคุณเกือบทั้งหมดอยู่ในภาษาเทมเพลตมากกว่าในซอร์ส Python
มีแคตตาล็อกอยู่แล้วใช่ไหม มันยังใช้งานได้ต่อไป
_("Hello {name}").format(name=name) กับ tr(t"Hello {name}") ผลิต msgid
เดียวกัน คำแปลที่มีอยู่จึงรอดผ่านการเปลี่ยนมาได้ —
การย้ายระบบ พาเดินตลอดการย้าย
แคตตาล็อกพูดอะไรได้บ้าง¶
คำแปลเปลี่ยนโครงสร้างของประโยคที่มันแปลไม่ได้ นั่นคือทั้งหมดของคำสัญญา
และทุกอย่างที่เหลือในเว็บไซต์นี้ล้วนสืบเนื่องมาจากมัน คำแปลอาจสลับลำดับหรือใช้
{name} ซ้ำได้ และเขียนคำอื่น ๆ รอบมันใหม่ทั้งหมดก็ได้ แต่จะตัดตัวยึดตำแหน่งทิ้ง
เสกอันใหม่ขึ้นมา เอื้อมผ่านมันเข้าไปในอ็อบเจกต์ของคุณ
หรือแนบการจัดรูปแบบของตัวเองไม่ได้
ไลบรารีตรวจสอบสิ่งนั้นตั้งแต่ขาเข้า — ตอนคอมไพล์แคตตาล็อก — และตรวจอีกครั้งตอนเรนเดอร์ ซึ่งนั่นคือความต่างระหว่างข้อผิดพลาด ที่ถูกพบตอนรีวิว กับข้อผิดพลาดที่ถูกพบโดยผู้ใช้
เพิ่งรู้จัก gettext? เวิร์กโฟลว์ทั้งหมดในสี่ประโยค
gettext คือวิธีมาตรฐานที่ซอฟต์แวร์ใช้ในการแปล ทั้งใน Python
และไกลกว่านั้นมาก โค้ดของคุณทำเครื่องหมายสตริงที่ต้องแปล
จากนั้น ตัวสกัดข้อความ จะรวบรวมมันเข้าไฟล์เทมเพลต (.pot)
แล้วนักแปล — ซึ่งมักไม่ใช่โปรแกรมเมอร์ — จะเติมคำแปลลงในไฟล์แคตตาล็อก
(.po) หนึ่งไฟล์ต่อหนึ่งภาษา ซึ่งจะถูกคอมไพล์เป็นไฟล์ไบนารี .mo
ที่แอปพลิเคชันของคุณโหลดตอนรันไทม์ ชื่อตามธรรมเนียมของฟังก์ชันแปลคือ
_ ดังนั้น _(t"Hello {name}") จึงอ่านได้ว่า "แปลประโยคนี้"
บทแนะนำ จะพาเดินครบทั้งเส้นทาง — ทำเครื่องหมาย สกัด
แปล คอมไพล์ รัน — ในเวลาราวห้านาที
ปัญหาที่มันแก้¶
f-string ถูกแทนค่าเสร็จเรียบร้อยก่อนที่ไลบรารีใดจะทันได้เห็นมัน —
f"Hello {name}" กลายเป็น "Hello Ada" ไปแล้ว
และการแปลเศษข้อความรอบ ๆ ค่าหนึ่ง ๆ จะทำลายไวยากรณ์ของภาษาส่วนใหญ่
ส่วน t-string (PEP 750) เก็บข้อความคงที่ ค่าที่ประเมินแล้ว นิพจน์ต้นทาง
การแปลงค่า และตัวระบุรูปแบบแยกจากกัน —
ซึ่งเป็นการแยกส่วนแบบที่แคตตาล็อกข้อความต้องการพอดี
สิ่งที่เปลี่ยนไปจากเดิม เมื่อเทียบกับ %(name)s,
.format() และ $-strings
อย่างไรก็ตาม ไม่มีส่วนใดใน gettext หรือ Babel ที่กำหนดว่า t-string จะกลายเป็นข้อความได้อย่างไร ไลบรารีนี้เป็นผู้ตัดสินใจเลือกแนวทางนั้น เขียนมันไว้เป็นข้อกำหนดที่มีการกำกับเวอร์ชัน และมาพร้อมชุดทดสอบความสอดคล้องสำหรับตรวจสอบ
กฎการออกแบบ¶
- แปลข้อความทั้งประโยคเสมอ ไม่แปลเศษเสี้ยวของประโยค
- รับเฉพาะชื่อตัวแปรอย่างง่ายเช่น
{name} - เก็บ
!rและ:.2fไว้ใต้การควบคุมของแอปพลิเคชัน นอกแคตตาล็อก - ให้นักแปลสลับลำดับและใช้ตัวยึดตำแหน่งที่รู้จักซ้ำได้ — แต่เรียกแอตทริบิวต์ไม่ได้ และเพิ่มพฤติกรรมการจัดรูปแบบเองไม่ได้
- ใช้ไฟล์ POT, PO และ MO แบบธรรมดา รวมถึงเครื่องมือที่อ่านไฟล์เหล่านี้ได้อยู่แล้ว
และนี่คือรายการคู่กันของสิ่งที่มันจงใจไม่ไปยุ่งด้วย: มันไม่แปลงตัวเลข สกุลเงิน หรือวันที่ให้เข้ากับท้องถิ่น — จงจัดรูปแบบสิ่งเหล่านั้นก่อน ด้วย Babel; มันไม่ escape ผลลัพธ์ที่เรนเดอร์แล้วสำหรับ HTML เชลล์ หรือเทอร์มินัล และมันตัดสินไม่ได้ว่าคำแปล ถูกต้อง หรือไม่ ตัดสินได้เพียงว่าตัวยึดตำแหน่งของมันยังครบถ้วน
การติดตั้ง¶
ต้องใช้ Python 3.14 ขึ้นไป การเรนเดอร์ไม่มี dependency ใด ๆ —
ใช้เพียง gettext จากไลบรารีมาตรฐานเท่านั้น ไม่มีอย่างอื่นอีก
การสกัดข้อความและการตรวจสอบแคตตาล็อกทำงานผ่าน Babel
จึงควรติดตั้ง extra นี้ในที่ที่ pybabel ทำงาน
ซึ่งมักเป็นสภาพแวดล้อมการพัฒนาหรือ CI มากกว่าอิมเมจสำหรับการใช้งานจริง:
ขั้นตอนถัดไป¶
เริ่มต้นที่นี่ — ไม่ต้องมีประสบการณ์ gettext มาก่อน:
- บทแนะนำ — จากไดเรกทอรีว่างเปล่าสู่คำแปลภาษาญี่ปุ่นที่ทำงานได้จริงในห้าขั้นตอน ทุกคำสั่งแสดงพร้อมผลลัพธ์ของมัน
- ทำไมต้อง t-string — ข้อความเดียวกันเขียนสี่แบบ
และสิ่งที่
%(name)s,.format()และ$-strings แต่ละแบบส่งต่อให้แคตตาล็อก
การใช้งาน — เอกสารอ้างอิงสำหรับการทำงาน:
- คู่มือ — API ตอนรันไทม์: ควรใช้จุดเข้าไหน รูปพหูพจน์ ภาษาแบบต่อคำขอ สตริงแบบเลื่อนการแปล และสิ่งที่เกิดขึ้นเมื่อแคตตาล็อกผิดพลาด
- การสกัดข้อความ — เอกสารอ้างอิง
pybabel: การตั้งค่า ชื่อฟังก์ชันแบบกำหนดเอง และวิธีที่เครื่องมือที่มีอยู่แล้วช่วยตรวจสอบแคตตาล็อกเหล่านี้ให้ฟรี ๆ - การใช้งานจริง — ลูปเดียวกันในแบบที่ทีมใช้จริง: รอบการอัปเดต รายการ fuzzy เกต CI แพลตฟอร์มการแปล และการจัดส่ง
- การย้ายระบบ — การรับสิ่งนี้มาใช้ในโปรเจกต์ที่มีแคตตาล็อกอยู่แล้ว ทีละจุดเรียกใช้
- สำหรับนักแปล —
หน้าเดียวที่ส่งมอบให้ใครก็ตามที่เป็นคนแก้ไขไฟล์
.po
ทำความเข้าใจ — จากประวัติศาสตร์ไปจนถึงการทำงานภายใน:
- ความเป็นมา — เหตุผลที่ไลบรารีนี้ถือกำเนิดขึ้น: สามสิบปีของ gettext, PEP สองฉบับ และการอภิปรายเรื่อง stdlib ที่ปิดลงโดยไม่มีคำตอบ
- หลุมพราง — สิ่งที่พังจริงจากการแปลเว็บไซต์นี้เป็นสามสิบห้าภาษา และครึ่งไหนที่เครื่องมือจับได้
- หลักการทำงาน — จากอ็อบเจกต์เทมเพลตของ PEP 750 ไปจนถึงสตริงที่เรนเดอร์เสร็จ และแคชที่ทำให้การตรวจสอบมีต้นทุนต่ำ
เอกสารอ้างอิง — ตัวสัญญา:
สถานะ¶
| เวอร์ชันแพ็กเกจ | 0.1.0a8 |
| ความเสถียรของ API | อัลฟา — Python API อาจยังเปลี่ยนแปลงได้ |
| ข้อกำหนด | v1 พร้อมชุดทดสอบความสอดคล้อง |
| Python | 3.14 ขึ้นไป ทดสอบบน 3.14, 3.14t (free-threaded) และ 3.15 |
| Babel | 2.18 ขึ้นไป และเฉพาะที่ซึ่ง pybabel ทำงานเท่านั้น |
| Dependency ตอนรันไทม์ | ไม่มี — ใช้ gettext ของไลบรารีมาตรฐาน |
| รูปแบบแคตตาล็อก | POT, PO และ MO แบบธรรมดา |
| การเปลี่ยนแปลง | CHANGELOG |
ยังเป็นรุ่นอัลฟา สัญญาถูกออกแบบให้เล็กโดยตั้งใจ และข้อกำหนดคือส่วนที่เสถียรของมัน ส่วน Python API อาจยังเปลี่ยนแปลงได้ ก่อนออกรุ่นเสถียร โปรเจกต์นี้ยังต้องการ fixture ภาษาที่หลากหลายขึ้น การติดตามประสิทธิภาพอย่างต่อเนื่อง การรีวิว API จากผู้ที่ใช้ gettext และ Babel อย่างจริงจัง และการทดสอบความเข้ากันได้กับ Python และ Babel ทุกรุ่นที่รองรับ
Issue และ pull request ยินดีต้อนรับเสมอ — ช่วงอัลฟาคือช่วงเวลาที่อินเทอร์เฟซยังคุ้มค่าแก่การถกเถียงที่สุด
เข้าร่วมชุมชน¶
- เลือก good first issue สำหรับการมีส่วนร่วมที่มีขอบเขตชัดเจน
- ถามคำถามเรื่องการใช้งานได้ใน Q&A Discussions
- นำเวิร์กโฟลว์ gettext จากงานจริงและไอเดียเกี่ยวกับ API มาแลกเปลี่ยนใน Ideas Discussions
- อ่าน คู่มือการมีส่วนร่วม ก่อนเปิด pull request