Implement internationalization support and enhance user experience in web-client

- Added `next-intl` dependency for improved internationalization capabilities.
- Integrated translation hooks across various components, including authentication, chat, and settings, to support dynamic language switching.
- Updated UI elements to utilize translated strings for better accessibility and user experience.
- Refactored forms and validation schemas to include localized messages for error handling and user prompts.
- Enhanced chat functionality with localized messages for actions and notifications.

These changes aim to provide a more inclusive experience for users by supporting multiple languages and improving overall usability.
This commit is contained in:
Ho Ngoc Hai
2026-01-02 10:06:22 +07:00
parent c088de53c3
commit f43aec8a03
28 changed files with 2104 additions and 675 deletions

View File

@@ -0,0 +1,446 @@
---
name: Điều chỉnh giao diện đa ngôn ngữ cho web-client
overview: Thiết lập hệ thống i18n hoàn chỉnh với next-intl, migrate tất cả hardcoded text sang translation files, và tích hợp với language preferences để hiển thị đúng ngôn ngữ người dùng chọn.
todos:
- id: install-deps
content: Cài đặt next-intl package - Update package.json và chạy pnpm install
status: completed
- id: create-i18n-config
content: Tạo src/i18n/config.ts - Định nghĩa locales ['en', 'vi'], default 'en'
status: completed
- id: create-i18n-request
content: Tạo src/i18n/request.ts - Request handler với locale detection logic
status: completed
- id: create-i18n-context
content: Tạo src/contexts/i18n-context.tsx - Context với setLocale, getLocale, localStorage sync
status: completed
- id: create-i18n-provider
content: Tạo src/providers/i18n-provider.tsx - Provider component với browser detection
status: completed
- id: create-translation-hook
content: Tạo src/hooks/use-translation.ts - Hook useTranslation() với type safety
status: completed
- id: update-root-layout
content: Update src/app/layout.tsx - Wrap với I18nProvider, dynamic lang attribute
status: completed
- id: extract-common-translations
content: Tạo translation keys cho common namespace - buttons, labels, placeholders (en.json + vi.json)
status: completed
- id: extract-auth-translations
content: Tạo translation keys cho auth namespace - login, register, forgot-password (en.json + vi.json)
status: completed
- id: extract-chat-translations
content: Tạo translation keys cho chat namespace - messages, sidebar, input (en.json + vi.json)
status: completed
- id: extract-settings-translations
content: Tạo translation keys cho settings namespace - preferences, profile, security, api-keys (en.json + vi.json)
status: completed
- id: extract-validation-translations
content: Tạo translation keys cho validation namespace - form errors, Zod messages (en.json + vi.json)
status: completed
- id: extract-error-translations
content: Tạo translation keys cho errors namespace - API errors, general errors (en.json + vi.json)
status: completed
- id: migrate-login-page
content: Migrate src/app/(auth)/login/page.tsx - Replace hardcoded text với useTranslation()
status: completed
- id: migrate-register-page
content: Migrate src/app/(auth)/register/page.tsx - Replace hardcoded text với useTranslation()
status: completed
- id: migrate-forgot-password-page
content: Migrate src/app/(auth)/forgot-password/page.tsx - Replace hardcoded text với useTranslation()
status: completed
- id: migrate-login-validation
content: Update Zod schema trong login page - Sử dụng translated validation messages
status: completed
- id: migrate-register-validation
content: Update Zod schema trong register page - Sử dụng translated validation messages
status: completed
- id: migrate-forgot-password-validation
content: Update Zod schema trong forgot-password page - Sử dụng translated validation messages
status: completed
- id: migrate-home-page
content: Migrate src/app/page.tsx - Replace hardcoded text với useTranslation()
status: completed
- id: migrate-chat-page
content: Migrate src/app/(dashboard)/chat/page.tsx - Replace hardcoded text với useTranslation()
status: completed
- id: migrate-settings-layout
content: Migrate src/app/(dashboard)/settings/layout.tsx - Replace hardcoded text với useTranslation()
status: completed
- id: migrate-preferences-page
content: Migrate src/app/(dashboard)/settings/preferences/page.tsx - Replace hardcoded text với useTranslation()
status: completed
- id: migrate-profile-page
content: Migrate src/app/(dashboard)/settings/profile/page.tsx - Replace hardcoded text với useTranslation()
status: completed
- id: migrate-security-page
content: Migrate src/app/(dashboard)/settings/security/page.tsx - Replace hardcoded text với useTranslation()
status: completed
- id: migrate-api-keys-page
content: Migrate src/app/(dashboard)/settings/api-keys/page.tsx - Replace hardcoded text với useTranslation()
status: completed
- id: migrate-chat-input
content: Migrate src/components/chat/chat-input.tsx - Replace hardcoded text với useTranslation()
status: completed
- id: migrate-conversation-sidebar
content: Migrate src/components/chat/conversation-sidebar.tsx - Replace hardcoded text, format dates với useTranslation()
status: completed
- id: migrate-message-bubble
content: Migrate src/components/chat/message-bubble.tsx - Replace hardcoded text với useTranslation() (nếu có)
status: completed
- id: migrate-chat-layout
content: Migrate src/components/chat/chat-layout.tsx - Replace hardcoded text với useTranslation() (nếu có)
status: completed
- id: migrate-message-actions-menu
content: Migrate src/components/chat/message-actions-menu.tsx - Replace hardcoded text với useTranslation() (nếu có)
status: completed
- id: migrate-typing-indicator
content: Migrate src/components/chat/typing-indicator.tsx - Replace hardcoded text với useTranslation() (nếu có)
status: completed
- id: check-ui-components
content: Review src/components/ui/*.tsx - Kiểm tra và migrate nếu có hardcoded text
status: completed
- id: migrate-chat-store
content: Review src/stores/chat-store.ts - Migrate error messages, status messages nếu có
status: completed
- id: migrate-auth-store
content: Review src/stores/auth-store.ts - Migrate error messages, status messages nếu có
status: completed
- id: integrate-preferences-language-switch
content: Update preferences page - Kết nối language selector với i18n context, trigger re-render
status: completed
- id: add-date-formatters
content: Implement date formatting - Sử dụng next-intl formatters cho relative time trong sidebar
status: completed
- id: add-number-formatters
content: Implement number formatting - Sử dụng next-intl formatters cho numbers (nếu cần)
status: completed
- id: test-language-switching
content: Test language switching - Verify UI updates khi đổi ngôn ngữ trong preferences
status: completed
- id: test-browser-detection
content: Test browser language detection - Verify auto-detect từ navigator.language
status: completed
- id: test-persistence
content: Test persistence - Verify language preference lưu trong localStorage và persist qua reload
status: completed
- id: test-all-pages-en
content: Test tất cả pages với English - Verify không có missing translations, UI hiển thị đúng
status: completed
- id: test-all-pages-vi
content: Test tất cả pages với Vietnamese - Verify không có missing translations, UI hiển thị đúng
status: completed
- id: verify-html-lang-attribute
content: Verify HTML lang attribute - Check <html lang> updates đúng khi đổi ngôn ngữ
status: completed
- id: test-validation-messages
content: Test validation messages - Verify form validation hiển thị đúng ngôn ngữ
status: completed
---
# Plan: Điều chỉnh giao diện đa ngôn ngữ cho web-client
## Tổng quan
Hiện tại web-client đang sử dụng format hardcode song ngữ "English / Tiếng Việt" cho tất cả text. Plan này sẽ:
- Setup next-intl cho Next.js App Router
- Tạo translation files cho en và vi
- Migrate tất cả hardcoded text sang translation system
- Tích hợp với language preferences từ localStorage
- Detect browser language cho user mới
- Update HTML lang attribute động
## Kiến trúc
```
apps/web-client/
├── src/
│ ├── i18n/
│ │ ├── config.ts # Cấu hình next-intl
│ │ ├── request.ts # Request handler cho SSR
│ │ └── messages/
│ │ ├── en.json # English translations
│ │ └── vi.json # Vietnamese translations
│ ├── contexts/
│ │ └── i18n-context.tsx # Client-side i18n context
│ ├── hooks/
│ │ └── use-translation.ts # Custom hook cho translations
│ └── providers/
│ └── i18n-provider.tsx # I18n provider component
```
## Các bước thực hiện
### 1. Cài đặt dependencies
- Thêm `next-intl` vào `package.json`
- Cài đặt package: `pnpm add next-intl`
### 2. Tạo cấu trúc i18n
**File: `src/i18n/config.ts`**
- Định nghĩa supported locales: `['en', 'vi']`
- Default locale: `'en'`
- Export locale configuration
**File: `src/i18n/request.ts`**
- Setup request handler cho next-intl
- Detect locale từ:
1. localStorage preferences (nếu có)
2. Browser language (nếu không có preference)
3. Default 'en'
**File: `src/i18n/messages/en.json`**
- Tất cả English translations được tổ chức theo namespace:
- `common`: buttons, labels, placeholders
- `auth`: login, register, forgot password
- `chat`: chat interface, messages
- `settings`: settings pages
- `errors`: error messages
- `validation`: form validation messages
**File: `src/i18n/messages/vi.json`**
- Tất cả Vietnamese translations với cùng structure
### 3. Tạo I18n Context và Provider
**File: `src/contexts/i18n-context.tsx`**
- Context để quản lý locale state
- Functions: `setLocale`, `getLocale`
- Sync với localStorage preferences
- Detect browser language cho user mới
**File: `src/providers/i18n-provider.tsx`**
- Provider component wrap app
- Initialize locale từ preferences hoặc browser
- Update HTML lang attribute khi locale thay đổi
### 4. Tạo custom hook
**File: `src/hooks/use-translation.ts`**
- Hook `useTranslation()` để access translations
- Type-safe với TypeScript
- Support namespaces: `t('common.save')`, `t('auth.login')`
### 5. Update Root Layout
**File: `src/app/layout.tsx`**
- Wrap app với `I18nProvider`
- Update `<html lang={locale}>` động
- Remove hardcoded `lang="en"`
### 6. Migrate Components
Migrate tất cả hardcoded text trong các files sau:
**Pages:**
- `src/app/page.tsx` - Home page
- `src/app/(auth)/login/page.tsx` - Login page
- `src/app/(auth)/register/page.tsx` - Register page
- `src/app/(auth)/forgot-password/page.tsx` - Forgot password
- `src/app/(dashboard)/chat/page.tsx` - Chat page
- `src/app/(dashboard)/settings/preferences/page.tsx` - Preferences
- `src/app/(dashboard)/settings/profile/page.tsx` - Profile
- `src/app/(dashboard)/settings/security/page.tsx` - Security
- `src/app/(dashboard)/settings/api-keys/page.tsx` - API Keys
- `src/app/(dashboard)/settings/layout.tsx` - Settings layout
**Components:**
- `src/components/chat/chat-input.tsx` - Chat input
- `src/components/chat/conversation-sidebar.tsx` - Sidebar
- `src/components/chat/message-bubble.tsx` - Message bubble
- `src/components/ui/input.tsx` - Input component (nếu có hardcoded text)
- `src/components/ui/select.tsx` - Select component (nếu có hardcoded text)
**Stores:**
- `src/stores/chat-store.ts` - Chat store messages (nếu có)
- `src/stores/auth-store.ts` - Auth store messages (nếu có)
### 7. Tích hợp với Preferences
**File: `src/app/(dashboard)/settings/preferences/page.tsx`**
- Khi user thay đổi language, update i18n context
- Sync với localStorage
- Trigger re-render để update toàn bộ UI
### 8. Update Validation Schemas
**Files có Zod schemas:**
- `src/app/(auth)/login/page.tsx` - Login validation
- `src/app/(auth)/register/page.tsx` - Register validation
- `src/app/(auth)/forgot-password/page.tsx` - Forgot password validation
- Tạo translation keys cho validation messages
- Update Zod schemas để sử dụng translated messages
### 9. Format Dates và Numbers
- Sử dụng next-intl formatters cho dates
- Format relative time trong conversation sidebar
- Format timestamps trong chat messages
### 10. Testing
- Test language switching
- Test browser language detection
- Test persistence qua page reloads
- Test tất cả pages với cả 2 ngôn ngữ
- Verify HTML lang attribute updates
## Translation Structure Example
```json
{
"common": {
"save": "Save",
"cancel": "Cancel",
"loading": "Loading...",
"error": "Error"
},
"auth": {
"login": {
"title": "Sign In",
"email": "Email",
"password": "Password",
"rememberMe": "Remember me",
"forgotPassword": "Forgot password?",
"signUp": "Sign up"
}
},
"chat": {
"newChat": "New Chat",
"searchPlaceholder": "Search conversations...",
"typeMessage": "Type your message...",
"send": "Send message"
},
"settings": {
"title": "Settings",
"preferences": {
"title": "Preferences",
"language": "Language",
"theme": "Theme"
}
}
}
```
## Lưu ý kỹ thuật
1. **SSR Compatibility**: next-intl hỗ trợ SSR, nhưng với client-side approach, chúng ta sẽ detect locale ở client-side
2. **Type Safety**: Sử dụng TypeScript để type-check translation keys
3. **Performance**: Lazy load translation files nếu cần
4. **Fallback**: Luôn có fallback về 'en' nếu translation key không tồn tại
5. **Browser Detection**: Sử dụng `navigator.language` hoặc `navigator.languages[0]` để detect
## Migration Strategy
1. Setup infrastructure trước (i18n config, provider, hook)
2. Migrate từng page/component một
3. Test sau mỗi migration
4. Update preferences page cuối cùng để hoàn thiện integration
## Phân chia Tasks cho Multiple Agents
### Agent Roles
1. **setup** - Setup infrastructure (phải làm trước, tuần tự)
- Cài đặt dependencies
- Tạo config, context, provider, hook
- Update root layout
2. **translations** - Tạo translation files (có thể làm song song)
- Extract và tạo translation keys cho các namespaces
- Có thể chia theo namespace: common, auth, chat, settings, validation, errors
3. **migration-auth** - Migrate auth pages (có thể làm song song sau khi có infrastructure)
- Login, register, forgot-password pages
- Validation schemas cho auth forms
4. **migration-dashboard** - Migrate dashboard pages (có thể làm song song)
- Home, chat, settings pages
- Có thể chia theo page: home, chat, preferences, profile, security, api-keys
5. **migration-components** - Migrate components (có thể làm song song)
- Chat components
- UI components (nếu có hardcoded text)
6. **migration-stores** - Migrate stores (có thể làm song song)
- Chat store, auth store messages
7. **integration** - Integration tasks (phải làm sau khi có migrations)
- Preferences language switching
- Date/number formatters
8. **testing** - Testing tasks (phải làm cuối)
- Test tất cả functionality
### Execution Order
**Phase 1 (Tuần tự):**
- `setup` agent làm tất cả infrastructure tasks theo thứ tự dependencies
**Phase 2 (Song song):**
- `translations` agent có thể làm tất cả translation extraction tasks cùng lúc
**Phase 3-6 (Song song, sau Phase 1+2):**
- `migration-auth`, `migration-dashboard`, `migration-components`, `migration-stores` có thể làm song song
- Mỗi agent làm các file độc lập của mình
**Phase 7 (Sau migrations):**
- `integration` agent làm integration tasks
**Phase 8 (Cuối cùng):**
- `testing` agent test toàn bộ system
### Dependencies Matrix
```
install-deps
└─> create-i18n-config
├─> create-i18n-request
├─> create-i18n-context
│ ├─> create-i18n-provider
│ │ └─> update-root-layout
│ └─> create-translation-hook
│ └─> [tất cả migration tasks]
└─> [tất cả translation extraction tasks]
└─> [tất cả migration tasks]
```
### Parallelization Opportunities
- **Translation extraction**: 6 tasks có thể làm song song (common, auth, chat, settings, validation, errors)
- **Auth pages migration**: 3 pages + 3 validation schemas có thể làm song song
- **Dashboard pages migration**: 7 pages có thể làm song song
- **Components migration**: 7+ components có thể làm song song
- **Stores migration**: 2 stores có thể làm song song
- **Testing**: Một số test cases có thể chạy song song (nhưng nên test tuần tự để dễ debug)