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:
@@ -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)
|
||||
Reference in New Issue
Block a user