This commit is contained in:
Your Name committed 2026-07-11 19:44:12 -04:00
1 parent fdb731c732
commit 862eeef48b
2 files changed
+62 -4

No files matched your search

+62
View File
@@ -0,0 +1,62 @@
# 🌍 คู่มือการเพิ่มภาษาใหม่ (Adding New Language Guide)
โปรเจกต์ HomAroma ถูกออกแบบฐานข้อมูลมาให้รองรับหลายภาษา (Multi-language / i18n) ไว้แล้วโดยสมบูรณ์ผ่านรูปแบบ Entity Translation การเพิ่มภาษาใหม่ในระบบ (เช่น ภาษาที่ 7, 8) **ไม่ต้องทำการแก้โค้ดฝั่ง Backend หรือ Database ใดๆ ทั้งสิ้น** (ไม่ต้อง Migrate DB)
คุณสามารถเพิ่มภาษาใหม่ได้ง่ายๆ โดยการแก้ไขโค้ดฝั่ง Frontend (`apps/spa` และ `apps/website`) เท่านั้น ใช้เวลาเพียงไม่กี่นาที
---
## 🛠 สิ่งที่ต้องทำ (แก้ไขใน Frontend เท่านั้น)
สมมติว่าเราต้องการเพิ่ม **ภาษาฝรั่งเศส (French)** โดยใช้รหัสภาษา `fr`
### ขั้นตอนที่ 1: เพิ่มไฟล์แปลข้อความ UI (Translation JSON)
ระบบเก็บข้อความบนหน้าเว็บ (UI Strings เช่น คำบนปุ่ม, เมนูพื้นฐาน, แจ้งเตือน) ไว้ในไฟล์ JSON
1. ไปที่ `apps/spa/src/locales/`
2. สร้างโฟลเดอร์ชื่อรหัสภาษาใหม่ เช่น `fr/`
3. คัดลอกไฟล์ `translation.json` จากโฟลเดอร์ภาษาอังกฤษ (`en/`) มาไว้ในโฟลเดอร์ใหม่ และดำเนินการแปลข้อความข้างในเป็นภาษาใหม่
4. ทำซ้ำขั้นตอนเดียวกันนี้ที่ `apps/website/src/locales/` (หรือก็อปปี้โฟลเดอร์ไปวางได้เลย)
### ขั้นตอนที่ 2: ลงทะเบียนภาษาใหม่ในไฟล์ i18n
เมื่อเตรียมไฟล์ JSON เสร็จแล้ว ต้องนำไฟล์นั้นมาลงทะเบียนให้ระบบอ่านค่าได้
**สำหรับ `apps/spa/src/i18n.ts` และ `apps/website/src/lib/i18n.ts`:**
เปิดไฟล์ตั้งค่า i18n ขึ้นมา และเพิ่มโค้ด 2 จุด ดังนี้:
```typescript
// 1. Import ไฟล์ JSON ของภาษาใหม่
import enTranslation from './locales/en/translation.json'
import thTranslation from './locales/th/translation.json'
// ...
import frTranslation from './locales/fr/translation.json' // <--- เพิ่มบรรทัดนี้
// ...
i18n.init({
resources: {
en: { translation: enTranslation },
th: { translation: thTranslation },
// ...
fr: { translation: frTranslation }, // <--- เพิ่มบรรทัดนี้
},
// ...
})
```
### ขั้นตอนที่ 3: อัปเดตเมนูตัวเลือกสลับภาษา (Language Switcher)
เข้าไปอัปเดต Component ที่ใช้เป็นปุ่มสลับภาษาบนหน้าเว็บ (มักจะอยู่ที่ `Navbar.tsx`, `Footer.tsx` หรือ `MobileDrawer.tsx`) ให้มีปุ่มตัวเลือกสำหรับภาษาฝรั่งเศส (หรือรหัส `fr`) เพิ่มเข้าไปในหน้าจอ เพื่อให้ผู้ใช้งานมองเห็นและกดเปลี่ยนภาษาได้
---
## ⚙️ ฝั่ง Backend / Database / MCP (ไม่ต้องแก้ไข)
- **Database (Prisma):** ตารางประเภท Translation เช่น `ProductTranslation`, `CategoryTranslation`, `PageTranslation` ฯลฯ ถูกออกแบบให้ฟิลด์ `langCode` เป็น `String` อิสระ ไม่ได้ถูกล็อกตายตัวด้วย `Enum` ฐานข้อมูลจึงพร้อมรับรหัสภาษาใหม่ (เช่น `fr`) เข้ามาเก็บทันทีโดยไม่ต้องแก้ Schema
- **MCP Server (AI Agents):** Tool ของ AI ถูกตั้งค่าให้รับ `langCode` เป็น string อิสระเช่นกัน ดังนั้น AI สามารถสร้างเนื้อหาสำหรับภาษาใหม่เข้าสู่ระบบได้เลยผ่านเครื่องมือเดิม
---
## 💡 สิ่งที่ต้องทำต่อไปหลังจากเพิ่มภาษาเสร็จแล้ว
เมื่อทำตามขั้นตอนฝั่ง Frontend เสร็จเรียบร้อย
ผู้ดูแลระบบ แอดมิน หรือ AI (ผ่านเครื่องมือ MCP) จะสามารถเริ่มยิงข้อมูล (เช่น สร้างสินค้า, สร้างหมวดหมู่, แปลบทความ) โดยส่งพารามิเตอร์ `langCode: "fr"` ผ่าน API เข้าสู่ระบบได้เลยทันที เมื่อหน้าเว็บมีการดึงข้อมูลด้วยภาษา `fr` ก็จะแสดงผลข้อมูลที่แอดมินใส่ไว้อย่างถูกต้อง
@@ -114,8 +114,6 @@ function HeroSection({ payload, lang }: { payload: Record<string, unknown>, lang
unoptimized
className="absolute inset-0 h-full w-full scale-[1.02] object-cover"
/>
<div className="ui-hero-overlay" />
<div className="ui-hero-overlay-strong" />
<div className="relative z-10 mx-auto mt-16 w-full max-w-4xl space-y-6 px-8 text-center md:mt-0">
<div className="space-y-6">
{tagline && (
@@ -229,7 +227,6 @@ function HeroV2Section({ payload, lang }: { payload: Record<string, unknown>, la
unoptimized
className="object-cover"
/>
<div className="absolute inset-0 bg-gradient-to-r from-surface-page/90 via-surface-page/50 to-transparent pointer-events-none" />
</div>
<div className="relative z-10 w-full max-w-7xl mx-auto px-6 md:px-12">
@@ -677,7 +674,6 @@ function HeroArticleSection({ payload, lang }: { payload: Record<string, unknown
{imageUrl && (
<>
<Image src={imageUrl} alt={title} fill unoptimized className="absolute inset-0 h-full w-full object-cover" />
<div className="ui-hero-overlay" />
</>
)}
<div className="relative z-10 mx-auto max-w-4xl space-y-6">