163 lines
3.8 KiB
Markdown
163 lines
3.8 KiB
Markdown
# Hướng dẫn Đa ngôn ngữ (i18n)
|
|
|
|
## Tổng quan
|
|
|
|
Hệ thống hỗ trợ 2 ngôn ngữ:
|
|
- **Tiếng Việt (vi)** - Ngôn ngữ chính
|
|
- **Tiếng Anh (en)** - Ngôn ngữ dự phòng
|
|
|
|
Cấu hình trong `.env`:
|
|
```
|
|
APP_LOCALE=vi
|
|
APP_FALLBACK_LOCALE=en
|
|
```
|
|
|
|
## Cấu trúc thư mục
|
|
|
|
```
|
|
lang/
|
|
├── en/
|
|
│ ├── app.php # UI chung: navigation, labels, status, widgets
|
|
│ ├── feedback.php # Domain feedback: services, notifications, interactions
|
|
│ └── enums.php # Labels cho enums
|
|
└── vi/
|
|
├── app.php
|
|
├── feedback.php
|
|
└── enums.php
|
|
```
|
|
|
|
## Quy tắc đặt tên Translation Keys
|
|
|
|
### 1. Resource Labels
|
|
```php
|
|
// Pattern: app.resource_{name}
|
|
'resource_feedbacks' => 'Phản ánh',
|
|
'resource_products' => 'Sản phẩm',
|
|
'resource_customers' => 'Khách hàng',
|
|
```
|
|
|
|
### 2. Status Labels
|
|
```php
|
|
// Pattern: app.status_{name}
|
|
'status_pending' => 'Chờ xử lý',
|
|
'status_processing' => 'Đang xử lý',
|
|
'status_resolved' => 'Đã xử lý',
|
|
'status_closed' => 'Đã đóng',
|
|
```
|
|
|
|
### 3. Form Labels
|
|
```php
|
|
// Pattern: app.{field_name}
|
|
'name' => 'Tên',
|
|
'email' => 'Email',
|
|
'phone' => 'Điện thoại',
|
|
```
|
|
|
|
### 4. Enum Labels
|
|
```php
|
|
// Pattern: enums.{enum_name}.{case_value}
|
|
'service.management_fee' => 'Phí quản lý',
|
|
'contract_status.active' => 'Đang hiệu lực',
|
|
```
|
|
|
|
### 5. Feedback Domain
|
|
```php
|
|
// Pattern: feedback.{action}_{context}
|
|
'already_closed' => 'Phiếu này đã được đóng.',
|
|
'close_permission_denied' => 'Chỉ lãnh đạo cấp phòng mới có quyền đóng phiếu.',
|
|
```
|
|
|
|
## Cách sử dụng trong code
|
|
|
|
### Resource Labels
|
|
```php
|
|
// Phải override getPluralLabel() - KHÔNG tự dịch
|
|
public static function getPluralLabel(): ?string
|
|
{
|
|
return __('app.resource_feedbacks');
|
|
}
|
|
|
|
// Phải override getNavigationGroup() - KHÔNG tự dịch
|
|
public static function getNavigationGroup(): ?string
|
|
{
|
|
return __('app.nav_customer_care');
|
|
}
|
|
```
|
|
|
|
### Form Fields
|
|
```php
|
|
// PHẢI thêm ->label() explicit
|
|
TextInput::make('name')->label(__('app.name'))
|
|
Select::make('status')->label(__('app.status'))
|
|
```
|
|
|
|
### RelationManager Title
|
|
```php
|
|
// Phải override getTitle() - KHÔNG dùng $title property
|
|
public static function getTitle(Model $ownerRecord, string $pageClass): string
|
|
{
|
|
return __('app.services');
|
|
}
|
|
```
|
|
|
|
### Widget Heading/Description
|
|
```php
|
|
// Phải override getHeading()/getDescription() - KHÔNG dùng property
|
|
public function getHeading(): string | Htmlable | null
|
|
{
|
|
return __('app.widget_avg_time_by_handler');
|
|
}
|
|
```
|
|
|
|
### Enum Labels
|
|
```php
|
|
public function label(): string
|
|
{
|
|
return match ($this) {
|
|
self::ACTIVE => __('enums.contract_status.active'),
|
|
};
|
|
}
|
|
```
|
|
|
|
## Cách thêm Translation Key mới
|
|
|
|
### Bước 1: Thêm vào `lang/vi/app.php`
|
|
```php
|
|
return [
|
|
// ... existing keys ...
|
|
'new_key' => 'Giá trị tiếng Việt',
|
|
];
|
|
```
|
|
|
|
### Bước 2: Thêm vào `lang/en/app.php`
|
|
```php
|
|
return [
|
|
// ... existing keys ...
|
|
'new_key' => 'English value',
|
|
];
|
|
```
|
|
|
|
### Bước 3: Sử dụng trong code
|
|
```php
|
|
echo __('app.new_key');
|
|
```
|
|
|
|
## Lưu ý quan trọng
|
|
|
|
1. **`$pluralLabel` property** - KHÔNG tự dịch, phải override `getPluralLabel()`
|
|
2. **`getNavigationGroup()`** - KHÔNG tự dịch, phải gọi `__()`
|
|
3. **`$heading`/`$description`** trong ChartWidget - KHÔNG tự dịch, phải override methods
|
|
4. **Form fields** - PHẢI thêm `->label()` explicit
|
|
5. **`$title`** trong RelationManager - KHÔNG tự dịch, phải override `getTitle()`
|
|
6. **Filament vendor** - Có sẵn 57 file dịch tiếng Việt, tự kích hoạt khi `APP_LOCALE=vi`
|
|
|
|
## Kiểm tra Translation
|
|
|
|
```bash
|
|
# Kiểm tra key có tồn tại không
|
|
php artisan tinker --execute="echo __('app.new_key');"
|
|
|
|
# Kiểm tra locale hiện tại
|
|
php artisan tinker --execute="echo app()->getLocale();"
|
|
```
|