3.8 KiB
3.8 KiB
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
// Pattern: app.resource_{name}
'resource_feedbacks' => 'Phản ánh',
'resource_products' => 'Sản phẩm',
'resource_customers' => 'Khách hàng',
2. Status Labels
// Pattern: app.status_{name}
'status_pending' => 'Chờ xử lý',
'status_processing' => 'Đang xử lý',
'status_resolved' => 'Đã xử lý',
'status_closed' => 'Đã đóng',
3. Form Labels
// Pattern: app.{field_name}
'name' => 'Tên',
'email' => 'Email',
'phone' => 'Điện thoại',
4. Enum Labels
// Pattern: enums.{enum_name}.{case_value}
'service.management_fee' => 'Phí quản lý',
'contract_status.active' => 'Đang hiệu lực',
5. Feedback Domain
// 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
// 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
// PHẢI thêm ->label() explicit
TextInput::make('name')->label(__('app.name'))
Select::make('status')->label(__('app.status'))
RelationManager Title
// 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
// 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
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
return [
// ... existing keys ...
'new_key' => 'Giá trị tiếng Việt',
];
Bước 2: Thêm vào lang/en/app.php
return [
// ... existing keys ...
'new_key' => 'English value',
];
Bước 3: Sử dụng trong code
echo __('app.new_key');
Lưu ý quan trọng
$pluralLabelproperty - KHÔNG tự dịch, phải overridegetPluralLabel()getNavigationGroup()- KHÔNG tự dịch, phải gọi__()$heading/$descriptiontrong ChartWidget - KHÔNG tự dịch, phải override methods- Form fields - PHẢI thêm
->label()explicit $titletrong RelationManager - KHÔNG tự dịch, phải overridegetTitle()- 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
# 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();"