หากคุณเคยทำงานกับ framework การแปลภาษาสากล (i18n) ที่มาพร้อมกับ Django คุณจะรู้ว่ามันจัดการสตริงแบบคงที่ได้ดี การห่อข้อความด้วย gettext() หรือใช้แท็กเทมเพลต {% trans %} จะดึงสตริงออกมาเป็นไฟล์ .po ซึ่งนักแปลจะเป็นคนกรอก ระบบนี้ผ่านการทดสอบมาอย่างดีและใช้งานได้ดีสำหรับโค้ดและเทมเพลต
แต่แล้วเนื้อหาที่เก็บอยู่ในฐานข้อมูลของคุณล่ะ?
ชื่อสินค้า หัวข้อบทความ คำอธิบายหมวดหมู่ คำตอบ FAQ เนื้อหาที่ผู้ใช้สร้างขึ้น สิ่งเหล่านี้ไม่ได้อยู่ในซอร์สโค้ดของคุณ คำสั่ง makemessages ของ Django จะไม่มีวันพบมัน และไฟล์ .po ก็ช่วยคุณไม่ได้ หากแอปพลิเคชันของคุณให้บริการเนื้อหาแบบไดนามิกแก่ผู้ใช้ในหลายภาษา คุณต้องใช้กลยุทธ์ที่แตกต่างออกไป
วิธีทำมีดังนี้: ใช้ django-modeltranslation เพื่อเพิ่มฟิลด์ที่แปลได้ลงในโมเดลของคุณ จากนั้นทำให้การแปลเป็นอัตโนมัติด้วย AI โดยใช้ TranslateBot
แพ็คเกจการแปลฐานข้อมูล Django
แพ็คเกจของบุคคลที่สามหลายตัวแก้ปัญหาการแปลฐานข้อมูล แต่ละตัวมีสถาปัตยกรรมที่แตกต่างกัน
django-modeltranslation
เพิ่มคอลัมน์เฉพาะภาษาลงในตารางที่มีอยู่โดยตรง ฟิลด์ title จะกลายเป็น title_en, title_de, title_fr และอื่น ๆ การ query ยังคงเร็วเพราะทุกอย่างอยู่ในตารางเดียวกัน อินเทอร์เฟซแอดมินแสดงทุกภาษาเคียงข้างกัน
- ข้อดี: ไม่ต้อง JOIN, query เร็ว, เข้าถึงแบบโปร่งใสผ่าน field descriptor, ระบบนิเวศที่เติบโตเต็มที่
- ข้อเสีย: ต้องเปลี่ยน schema ทุกครั้งที่เพิ่มภาษาใหม่, ตารางกว้างขึ้น
django-parler
สร้างตารางแปลแยกสำหรับแต่ละโมเดล ตารางเดิมยังคงสะอาด และการแปลจะถูกเก็บในตารางที่เกี่ยวข้องซึ่งเชื่อมต่อด้วย foreign key
- ข้อดี: schema สะอาด, เพิ่มภาษาได้ง่ายโดยไม่ต้อง migration
- ข้อเสีย: ต้องใช้ JOIN สำหรับเนื้อหาที่แปลแล้ว, รูปแบบ query ซับซ้อนขึ้นเล็กน้อย
django-translations
ใช้ตารางแปลเดียวกับ generic foreign key ที่ชี้กลับไปยังโมเดลใดก็ได้ การแปลทั้งหมดของทุกโมเดลจะอยู่ในตารางเดียว
- ข้อดี: เปลี่ยน schema น้อยที่สุด, ใช้กับโมเดลใดก็ได้
- ข้อเสีย: query แบบ generic foreign key อาจช้า, API ไม่โปร่งใสนัก
ฟิลด์ JSON แบบ Manual
คุณสามารถเก็บการแปลใน JSONField ได้:
class Product(models.Model):
name_translations = models.JSONField(default=dict)
# {"en": "Running Shoes", "de": "Laufschuhe", "fr": "Chaussures de course"}
- ข้อดี: ไม่ต้องพึ่ง dependency เพิ่มเติม, ยืดหยุ่น
- ข้อเสีย: ไม่มีการรวม ORM, ไม่มีการรองรับ admin, ต้องทำเองทั้งหมด
ควรใช้ตัวไหน?
สำหรับโปรเจกต์ส่วนใหญ่ django-modeltranslation เป็นตัวเลือกที่ดีที่สุด เป็นแพ็คเกจที่เติบโตเต็มที่ที่สุด มีการรวมเข้ากับ Django admin ดีที่สุด และเก็บข้อมูลทั้งหมดในตารางเดียวกันเพื่อ query ที่เร็ว ข้อแลกเปลี่ยน (ตารางกว้างขึ้นและต้อง migration ทุกครั้งที่เพิ่มภาษาใหม่) สามารถจัดการได้สำหรับแอปพลิเคชันส่วนใหญ่ ส่วนที่เหลือของคู่มือนี้ใช้ django-modeltranslation
การตั้งค่า django-modeltranslation ทีละขั้นตอน
ขั้นตอนที่ 1: ติดตั้งแพ็คเกจ
TranslateBot รวม django-modeltranslation เป็น dependency ที่เลือกได้ ติดตั้งทั้งสองพร้อมกัน:
pip install translatebot-django[modeltranslation]
หรือถ้าคุณใช้ uv:
uv add --dev translatebot-django[modeltranslation]
ขั้นตอนที่ 2: กำหนดค่า Django Settings
สองสิ่งที่สำคัญใน settings.py: ลำดับแอปและรายการภาษา
# settings.py
INSTALLED_APPS = [
'modeltranslation', # Must be BEFORE django.contrib.admin
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
# Your apps
'shop',
'translatebot_django',
]
LANGUAGE_CODE = 'en'
LANGUAGES = [
('en', 'English'),
('de', 'German'),
('fr', 'French'),
('nl', 'Dutch'),
]
แอป modeltranslation ต้องอยู่ก่อน django.contrib.admin เพื่อให้สามารถ patch คลาสแอดมินเพื่อแสดงฟิลด์การแปลได้
ขั้นตอนที่ 3: ลงทะเบียนโมเดลสำหรับการแปล
สร้างไฟล์ translation.py ในแต่ละแอปที่มีโมเดลที่แปลได้ สำหรับแอปร้านค้า e-commerce:
# shop/translation.py
from modeltranslation.translator import register, TranslationOptions
from .models import Product, Category
@register(Product)
class ProductTranslationOptions(TranslationOptions):
fields = ('name', 'description', 'short_description')
@register(Category)
class CategoryTranslationOptions(TranslationOptions):
fields = ('name', 'description')
รวมเฉพาะฟิลด์ที่มีข้อความที่มนุษย์อ่านได้ อย่าลงทะเบียนฟิลด์อย่างเช่น slug, price หรือ sku
ขั้นตอนที่ 4: สร้างและรัน Migration
python manage.py makemigrations
python manage.py migrate
หลังจากนี้ ตาราง shop_product ของคุณจะมีคอลัมน์ใหม่:
| Column | Type |
|---|---|
name |
varchar(200) |
name_en |
varchar(200) |
name_de |
varchar(200) |
name_fr |
varchar(200) |
name_nl |
varchar(200) |
description |
text |
description_en |
text |
description_de |
text |
description_fr |
text |
description_nl |
text |
short_description |
text |
short_description_en |
text |
short_description_de |
text |
short_description_fr |
text |
short_description_nl |
text |
ทุกภาษาที่คุณกำหนดใน LANGUAGES จะได้คอลัมน์ของตัวเองสำหรับแต่ละฟิลด์ที่ลงทะเบียน
ปัญหา: ฟิลด์การแปลที่ว่างเปล่า
ตอนนี้คุณมี schema พร้อมแล้ว แต่ทุกคอลัมน์ _de, _fr และ _nl ยังว่างเปล่า หากคุณมีสินค้า 500 รายการพร้อมฟิลด์ที่แปลได้ 3 ฟิลด์และภาษาเป้าหมาย 3 ภาษา นั่นคือ 4,500 ฟิลด์ว่างที่รอให้กรอก
การแปลเนื้อหาเหล่านั้นด้วยมือไม่เป็นจริง แม้จะใช้บริการแปลมืออาชีพ คุณก็ยังต้องส่งออกข้อมูล ส่งไป รอการส่งมอบ และนำเข้าผลลัพธ์กลับ สำหรับทีมเล็ก ๆ หรือนักพัฒนาคนเดียว สิ่งนี้มักหมายความว่าฟีเจอร์นี้จะไม่ถูกปล่อยออกมา
นี่คือจุดที่ TranslateBot เข้ามา
ทำให้การแปลเป็นอัตโนมัติด้วย TranslateBot
คำสั่งจัดการ translate ของ TranslateBot สามารถกรอกฟิลด์ว่างทั้งหมดโดยใช้ AI กำหนดค่า API key ของคุณก่อน:
# settings.py
TRANSLATEBOT_API_KEY = os.getenv("OPENAI_API_KEY")
TRANSLATEBOT_MODEL = "gpt-4o-mini" # Fast and cost-effective
จากนั้นแปลโมเดลที่ลงทะเบียนทั้งหมดเป็นภาษาเป้าหมาย:
python manage.py translate --target-lang de --models
คำสั่งเดียวนี้ค้นหาทุกโมเดลที่ลงทะเบียนกับ django-modeltranslation ระบุฟิลด์ที่ว่างสำหรับภาษาเป้าหมาย และกรอกด้วยการแปลที่สร้างโดย AI
แปลโมเดลเฉพาะ
หากคุณต้องการแปลเฉพาะสินค้าไม่ใช่หมวดหมู่:
python manage.py translate --target-lang de --models Product
หรือหลายโมเดลเฉพาะ:
python manage.py translate --target-lang de --models Product Category
ดูตัวอย่างด้วย Dry Run
ดูตัวอย่างก่อนเขียนลงฐานข้อมูลเสมอ:
python manage.py translate --target-lang de --models --dry-run
สิ่งนี้แสดงให้คุณเห็นว่าอะไรจะถูกแปลโดยไม่แก้ไขระเบียนใด ๆ
แปลเนื้อหาที่มีอยู่ใหม่
โดยค่าเริ่มต้น TranslateBot จะข้ามฟิลด์ที่มีการแปลอยู่แล้ว หากต้องการเขียนทับการแปลที่มีอยู่ (เช่น หลังจากปรับปรุงโมเดล AI หรือเพิ่มบริบท):
python manage.py translate --target-lang de --models --overwrite
แปลทุกภาษาพร้อมกัน
หากคุณไม่ใส่ --target-lang และมี LANGUAGES กำหนดไว้ใน settings TranslateBot จะแปลเป็นทุกภาษาที่กำหนดค่าไว้:
python manage.py translate --models
วิธีการทำงานของ Pipeline การแปล
นี่คือสิ่งที่เกิดขึ้นเมื่อคุณรันคำสั่ง translate
-
การค้นหา. TranslateBot query registry ของ django-modeltranslation เพื่อค้นหาโมเดลที่ลงทะเบียนทั้งหมดและฟิลด์ที่แปลได้
-
การตรวจจับแหล่งที่มา. สำหรับแต่ละระเบียน จะอ่านเนื้อหาต้นฉบับ ตรวจสอบฟิลด์พื้นฐานก่อน (เช่น
name) จากนั้น fallback ไปยังฟิลด์เฉพาะภาษาแรกที่มีข้อมูล (เช่นname_en) ระเบียนที่ไม่มีเนื้อหาต้นฉบับจะถูกข้าม -
การจัดกลุ่ม. ระเบียนถูกจัดกลุ่มเป็น batch และส่งไปยังผู้ให้บริการ AI ซึ่งทำให้การเรียก API มีประสิทธิภาพและหลีกเลี่ยงการถูกจำกัดอัตรา
-
การแปล. แต่ละ batch ถูกแปลโดยใช้โมเดล AI ที่กำหนดค่าไว้ คุณสามารถใช้ผู้ให้บริการ LLM ใดก็ได้ที่ LiteLLM รองรับ (OpenAI, Anthropic, Google, Azure และอื่น ๆ อีกมากมาย) หรือ DeepL
-
การเขียนแบบ Atomic. การอัปเดตฐานข้อมูลทั้งหมดสำหรับการรันแปลจะถูกห่อในธุรกรรมเดียว หากมีข้อผิดพลาด เช่น ข้อผิดพลาด API หรือการละเมิดข้อจำกัดฐานข้อมูล จะไม่มีข้อมูลบางส่วนถูกบันทึก ทั้งหมดหรือไม่มีเลย
ตัวอย่าง Workflow แบบเต็ม
นี่คือตัวอย่างเต็มตั้งแต่การกำหนดโมเดลจนถึงเนื้อหาที่แปลแล้ว โดยใช้โมเดล Product สำหรับ e-commerce
กำหนดโมเดล
# shop/models.py
from django.db import models
class Product(models.Model):
name = models.CharField(max_length=200)
description = models.TextField()
short_description = models.CharField(max_length=500, blank=True)
price = models.DecimalField(max_digits=10, decimal_places=2)
sku = models.CharField(max_length=50, unique=True)
created_at = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.name
ลงทะเบียนสำหรับการแปล
# shop/translation.py
from modeltranslation.translator import register, TranslationOptions
from .models import Product
@register(Product)
class ProductTranslationOptions(TranslationOptions):
fields = ('name', 'description', 'short_description')
รัน Migration
python manage.py makemigrations shop
python manage.py migrate
เพิ่มบริบทการแปล (ไม่บังคับ)
สร้างไฟล์ TRANSLATING.md ในรูทโปรเจกต์ของคุณเพื่อให้บริบทเกี่ยวกับโดเมนสินค้าของคุณแก่ AI:
# Translation Context
## About This Project
E-commerce store for outdoor sports equipment.
## Terminology
- "trail runners" refers to trail running shoes, not people
- Keep brand names (Nike, Salomon, Arc'teryx) untranslated
- "Gore-Tex" is a brand name, do not translate
## Tone
- Use informal "du" form in German
- Product descriptions should sound enthusiastic but not exaggerated
แปล
# Preview first
python manage.py translate --target-lang de --models Product --dry-run
# Apply translations
python manage.py translate --target-lang de --models Product
ผลลัพธ์:
Translating Product model fields to German (de)...
Found 142 products with untranslated fields
Translating batch 1/15...
Translating batch 2/15...
...
Translating batch 15/15...
Successfully translated 142 products
ตรวจสอบใน Admin
เปิด Django admin แล้วไปที่สินค้าใดก็ได้ คุณจะเห็นฟิลด์การแปลถูกกรอกแล้ว:
- Name [de]: Ultraleichte Trail-Laufschuhe
- Description [de]: Diese leichten Trail-Laufschuhe bieten hervorragenden Grip...
- Short description [de]: Leicht, schnell und griffig auf jedem Untergrund.
ทำซ้ำสำหรับแต่ละภาษาเป้าหมาย:
python manage.py translate --target-lang fr --models Product
python manage.py translate --target-lang nl --models Product
หรือแปลทุกภาษาพร้อมกัน:
python manage.py translate --models Product
แนวทางปฏิบัติที่ดีที่สุด
สำรองฐานข้อมูลของคุณก่อนรันการแปลจำนวนมากบน production TranslateBot ใช้ธุรกรรมแบบ atomic ดังนั้นการรันที่ล้มเหลวจะไม่ทิ้งข้อมูลบางส่วนไว้ แต่การมีข้อมูลสำรองจะให้คุณมีวิธีย้อนกลับหากคุณภาพการแปลไม่เป็นไปตามที่คาดหวัง
# PostgreSQL example
pg_dump mydb > backup_before_translation.sql
ใช้ dry run ก่อน รัน --dry-run ก่อนใช้การแปลกับโมเดลหรือภาษาใหม่เสมอ ตรวจสอบผลลัพธ์เพื่อให้แน่ใจว่าเนื้อหาต้นฉบับถูกตรวจจับอย่างถูกต้องและการแปลดูสมเหตุสมผล
แปลทีละโมเดลสำหรับฐานข้อมูลขนาดใหญ่ ซึ่งทำให้ง่ายต่อการตรวจสอบผลลัพธ์และรันโมเดลเฉพาะใหม่หากจำเป็น
python manage.py translate --target-lang de --models Product
python manage.py translate --target-lang de --models Category
python manage.py translate --target-lang de --models Article
เพิ่มบริบทการแปล ไฟล์ TRANSLATING.md ที่มีศัพท์เฉพาะโดเมนและแนวทางเรื่องน้ำเสียงจะช่วยปรับปรุงคุณภาพการแปลได้อย่างมาก สิ่งนี้สำคัญเป็นพิเศษสำหรับสาขาเฉพาะทางเช่น การแพทย์ กฎหมาย หรือผลิตภัณฑ์ทางเทคนิค
รักษาภาษาต้นฉบับให้มีข้อมูลอยู่เสมอ TranslateBot อ่านจากฟิลด์พื้นฐานหรือฟิลด์ภาษาต้นฉบับ ตรวจสอบให้แน่ใจว่ากระบวนการป้อนข้อมูลของคุณกรอกภาษาต้นฉบับเสมอ ฟิลด์ต้นฉบับที่ว่างหมายถึงการแปลที่ว่าง
รวมกับการแปลไฟล์ PO เพื่อครอบคลุมทั้งหมด แปลทั้งสตริงในโค้ดและเนื้อหาฐานข้อมูล:
# Static strings in code and templates
python manage.py makemessages -l de -l fr -l nl
python manage.py translate
python manage.py compilemessages
# Dynamic content in the database
python manage.py translate --models
ด้วยวิธีนี้ทุกสตริงที่ผู้ใช้เห็น ไม่ว่าจะมาจากเทมเพลตหรือฐานข้อมูล จะถูกแปลแล้ว
ขั้นตอนถัดไป
- อ่านเอกสารอ้างอิงคำสั่งฉบับเต็มสำหรับตัวเลือกทั้งหมดที่มี
- ตั้งค่าการรวม CI เพื่อตรวจสอบการแปลที่หายไปโดยอัตโนมัติ
- สำรวจโมเดล AI ที่รองรับ เพื่อหาสมดุลที่ดีที่สุดระหว่างคุณภาพและต้นทุนสำหรับโปรเจกต์ของคุณ