Some checks failed
CI / Lint → Typecheck → Test → Build (22) (push) Failing after 18s
CI / E2E Tests (push) Has been skipped
CodeQL Analysis / CodeQL (javascript-typescript) (push) Failing after 2m15s
Deploy / Build API Image (push) Failing after 28s
Deploy / Build Web Image (push) Failing after 16s
Deploy / Build AI Services Image (push) Failing after 17s
E2E Tests / Playwright E2E (push) Failing after 31s
Security Scanning / Dependency Audit (pnpm) (push) Failing after 3s
Security Scanning / Trivy Scan — API Image (push) Failing after 1m46s
Security Scanning / Trivy Scan — Web Image (push) Failing after 1m7s
Security Scanning / Trivy Scan — AI Services Image (push) Failing after 53s
Security Scanning / Trivy Filesystem Scan (push) Failing after 35s
Deploy / Deploy to Staging (push) Has been skipped
Deploy / Smoke Test Staging (push) Has been skipped
Deploy / Deploy to Production (push) Has been skipped
Deploy / Smoke Test Production (push) Has been skipped
Security Scanning / Security Gate (push) Failing after 0s
Deploy / Rollback Staging (push) Has been skipped
Deploy / Rollback Production (push) Has been skipped
Hoàn tất đợt cuối của nhiệm vụ chuyển toàn bộ tài liệu sang tiếng Việt. Đã dịch 22 file `.md` còn sót (~9.7k dòng) — gồm RUNBOOK, audits, docs/architecture, docs/load-testing, libs READMEs và các quick references. Giữ nguyên code blocks, đường dẫn, identifier kỹ thuật, URL và biến môi trường. Co-Authored-By: Paperclip <noreply@paperclip.ing>
10 KiB
10 KiB
GoodGo Frontend: Tham chiếu nhanh triển khai i18n + A11y
🎯 Những phát hiện chính trong nháy mắt
Trạng thái hiện tại
- ✅ Next.js 15 với App Router (cấu trúc tốt)
- ✅ React 18 + TypeScript (an toàn kiểu)
- ✅ Tailwind CSS với hỗ trợ dark mode (theme dựa trên HSL)
- ✅ Thư viện component tốt (~35 component)
- ✅ Một số kiến thức cơ bản về A11y đã có (HTML ngữ nghĩa, ARIA labels, skip link)
- ❌ CHƯA thiết lập i18n (tất cả tiếng Việt được hardcode)
- ❌ Thiếu sót A11y (quản lý focus, một số ARIA còn thiếu, tương phản màu chưa xác định)
Điểm vào chiến lược cho việc triển khai
1. Điểm vào i18n (Ưu tiên 1)
Files to modify for i18n:
├── app/layout.tsx → Add i18n provider
├── middleware.ts → Add locale routing
├── app/(public)/layout.tsx → Navigation text
├── app/(auth)/login/page.tsx → Form labels + errors
├── app/(auth)/register/page.tsx → Form labels + errors
├── components/listings/listing-form-steps.tsx → Multi-step form labels
├── components/search/filter-bar.tsx → Filter options + city names
├── lib/validations/*.ts → Zod error messages
└── [All other components with text]
Total files to update: ~25-30 files with hardcoded strings
2. Sửa lỗi A11y quan trọng (Ưu tiên 1.5)
Components needing A11y updates:
├── components/ui/dialog.tsx → Focus trapping + focus restoration
├── components/listings/image-gallery.tsx → Keyboard nav + ARIA
├── components/search/filter-bar.tsx → Proper labeling + ARIA
├── app/(dashboard)/layout.tsx → Tab focus management
└── Across all forms → Error message association
Tasks:
- Add focus trapping in modals
- Verify color contrast (WCAG AA)
- Add aria-busy to loading states
- Add proper aria-label to icon buttons
- Link form errors to inputs with aria-describedby
3. Cấu trúc file Message cho i18n
public/locales/
├── en.json
│ ├── common: { home, search, dashboard, logout, ... }
│ ├── auth: { login, register, email, password, ... }
│ ├── property: { apartment, house, villa, ... }
│ ├── transaction: { sale, rent, ... }
│ ├── directions: { north, south, east, ... }
│ ├── status: { draft, active, sold, ... }
│ ├── validation: { required, min_length, ... }
│ └── errors: { oauth_failed, access_denied, ... }
└── vi.json
└── [Same structure]
📋 Checklist triển khai
Giai đoạn 1: Thiết lập (2-3 giờ)
- Cài đặt gói
next-intl - Tạo các file message (en.json, vi.json)
- Cập nhật next.config.js cho routing i18n
- Tạo cấu hình i18n (config.ts)
- Cập nhật middleware.ts để phát hiện locale
- Bao bọc root layout bằng provider i18n
Giai đoạn 2: Tái cấu trúc cốt lõi (6-8 giờ)
- Cập nhật root layout & metadata
- Tái cấu trúc tất cả validation (Zod) để sử dụng messages
- Trích xuất chuỗi component sang useTranslations()
- Cập nhật tất cả các enum (TRANSACTION_TYPES, PROPERTY_TYPES, v.v.) để sử dụng i18n
- Cập nhật các page layout (public, auth, dashboard)
- Cập nhật toàn bộ nội dung trang
Giai đoạn 3: Cập nhật component (4-6 giờ)
- Cập nhật tất cả các component UI
- Cập nhật các component form
- Cập nhật các component navigation
- Cập nhật các component search/filter
- Cập nhật form đăng tin (listing form)
Giai đoạn 4: Sửa lỗi A11y (4-6 giờ)
- Sửa quản lý focus trong dialog
- Thêm focus trapping
- Cập nhật liên kết lỗi form (aria-describedby)
- Thêm aria-busy cho trạng thái loading
- Thêm aria-label cho các nút biểu tượng
- Xác minh tương phản màu
- Cập nhật thiết lập test cho i18n
Giai đoạn 5: Test & QA (3-4 giờ)
- Test cả hai locale trên tất cả các trang
- Chạy kiểm tra khả năng tiếp cận bằng axe DevTools
- Test điều hướng bằng bàn phím
- Test tương thích screen reader
- Cập nhật unit test cho i18n
🗣️ Kiểm kê nội dung văn bản
Navigation & Layout (~15 mục)
| Vị trí | Văn bản | Trạng thái |
|---|---|---|
| Public header | Trang chủ, Tìm kiếm, Đăng nhập, Đăng ký | ❌ Hardcoded |
| Dashboard nav | 8 mục nav | ❌ Hardcoded |
| Footer | 4 phần | ❌ Hardcoded |
Forms & Validation (~40+ mục)
| Vị trí | Loại | Số lượng | Trạng thái |
|---|---|---|---|
| Login form | Nhãn + lỗi | 8 | ❌ Hardcoded |
| Register form | Nhãn + lỗi | 10 | ❌ Hardcoded |
| Listing form | Nhãn đa bước | 25+ | ❌ Hardcoded |
| Search filters | Nhãn tùy chọn | 30+ | ❌ Hardcoded |
| Zod validation | Thông báo lỗi | 20+ | ❌ Hardcoded |
Enum & Hằng số (~50+ mục)
| File | Mục | Trạng thái |
|---|---|---|
| TRANSACTION_TYPES | 2 nhãn | ❌ Hardcoded |
| PROPERTY_TYPES | 6 nhãn | ❌ Hardcoded |
| LISTING_STATUSES | 8 nhãn | ❌ Hardcoded |
| DIRECTIONS | 8 nhãn | ❌ Hardcoded |
| CITIES | 13 tên | ❌ Hardcoded |
| PRICE_RANGES | 6 khoảng | ❌ Hardcoded |
Nội dung trang (~30 mục)
| Trang | Phần | Trạng thái |
|---|---|---|
| Trang landing | Hero, search, stats, CTA | ❌ Hardcoded |
| Kết quả tìm kiếm | Không có kết quả, loading, header | ❌ Hardcoded |
| Dashboard | Tiêu đề phần, trạng thái rỗng | ❌ Hardcoded |
🔑 Các file quan trọng cho i18n
Các file phải cập nhật (Blocker)
- middleware.ts — Định tuyến locale
- app/layout.tsx — Thiết lập provider i18n
- lib/validations/*.ts — Tích hợp messages
- lib/*.ts — Bất kỳ xử lý thông báo lỗi API nào
Các file ưu tiên cao
- app/(public)/layout.tsx — Navigation
- app/(auth)/login/page.tsx — Form xác thực
- components/listings/listing-form-steps.tsx — Forms
- components/search/filter-bar.tsx — Bộ lọc
Các file ưu tiên trung bình
- Tất cả các component trang
- Tất cả các component UI có văn bản
- Các component error boundary
♿ Ưu tiên triển khai A11y
Sửa lỗi quan trọng WCAG 2.1 AA
-
Quản lý focus (Cấp A)
- Thêm focus trap trong
dialog.tsx - Khôi phục focus khi đóng dialog
- Chỉ báo focus rõ ràng trên tất cả các nút
- Thêm focus trap trong
-
Tương phản màu (Cấp AA)
- Chạy kiểm tra axe DevTools
- Sửa văn bản có tỷ lệ < 4.5:1
- Sửa đồ họa có tỷ lệ < 3:1
-
Khả năng tiếp cận form (Cấp A)
- Liên kết tất cả thông báo lỗi với aria-describedby
- Gắn nhãn đúng cách với htmlFor
- Nhóm fieldset cho các form phức tạp
-
Trạng thái Loading (Cấp A)
- Thêm aria-busy cho spinner
- Thêm aria-label kèm ngữ cảnh
-
Nút biểu tượng (Cấp A)
- Tất cả các nút chỉ có biểu tượng cần aria-label
- Nút bật/tắt theme đã có nhãn ✓
Các cải tiến A11y nên có
- Skip link đã có sẵn ✓
- HTML ngữ nghĩa đã được sử dụng ✓
- Role="alert" trên lỗi ✓
- aria-invalid trên các trường form ✓
📦 Các phụ thuộc cần thêm
npm install next-intl
# No new devDependencies needed if using next-intl
# Testing with mocked i18n available
Tổng kích thước cài đặt: ~500KB đã minify
🧪 Chiến lược test
Unit Tests
// vitest.setup.ts - Mock i18n
vi.mock('next-intl', () => ({
useTranslations: () => (key) => mockMessages[key]
}));
Component Tests
// Test both locales
describe('LoginForm', () => {
it('renders Vietnamese labels', () => { ... });
it('renders English labels', () => { ... });
});
E2E Tests
// Test locale switching
- /en/login → English
- /vi/login → Vietnamese
- /en/dashboard → English dashboard
📊 Lộ trình ước tính
| Giai đoạn | Thời gian | Công sức |
|---|---|---|
| Thiết lập | 2-3h | Thấp |
| Tái cấu trúc cốt lõi | 6-8h | Trung bình |
| Components | 4-6h | Trung bình |
| Sửa lỗi A11y | 4-6h | Thấp-Trung bình |
| Testing | 3-4h | Trung bình |
| Tổng | 19-27h | ~3-4 ngày |
🚀 Thứ tự triển khai (Khuyến nghị)
- Thiết lập hạ tầng i18n (tạo nền tảng)
- Cập nhật middleware + root layout (kích hoạt routing)
- Trích xuất & tập trung tất cả văn bản (công việc chính)
- Sửa các vấn đề A11y (song song với #3)
- Test kỹ lưỡng (xác minh cuối cùng)
💡 Cơ hội thắng nhanh
Những việc có thể làm ngay:
- Tạo cấu trúc file message (30 phút)
- Thêm focus trap cho dialog (30 phút)
- Thêm aria-busy cho spinner (20 phút)
- Kiểm tra tương phản màu (1 giờ)
- Aria-label cho nút biểu tượng (30 phút)
📝 Ghi chú khi triển khai
Phát hiện locale (middleware)
// Check in order: URL > cookie > header > default
function getLocale(request) {
// 1. URL pathname: /en/* or /vi/*
// 2. Cookie: goodgo_locale
// 3. Header: Accept-Language
// 4. Default: vi
}
Chiến lược dự phòng Message
// If translation missing, use English as fallback
// Otherwise fallback to Vietnamese (primary)
Cân nhắc về hiệu năng
- Giữ các file message < 100KB mỗi file
- Lazy load message theo trang nếu cần
- Static generation cho các trang quan trọng về SEO
Cập nhật lần cuối: Ngày 9 tháng 4 năm 2026
Phiên bản: 1.0 - Trước triển khai
Độ tin cậy: Cao