feat: add i18n support for Vietnamese and English
This commit is contained in:
107
AGENTS.md
107
AGENTS.md
@@ -68,11 +68,19 @@ minicrm/
|
||||
│ │ │ ├── Customers/
|
||||
│ │ │ │ └── RelationManagers/FeedbacksRelationManager.php
|
||||
│ │ │ ├── FeedbackChannels/
|
||||
│ │ │ └── FeedbackTags/
|
||||
│ │ │ ├── FeedbackTags/
|
||||
│ │ │ ├── Contracts/
|
||||
│ │ │ ├── Users/
|
||||
│ │ │ └── Roles/
|
||||
│ │ └── Widgets/
|
||||
│ │ ├── ResolvedTicketsWidget.php # Dashboard: resolved tickets table
|
||||
│ │ ├── AvgProcessingTimeWidget.php # Dashboard: stats overview
|
||||
│ │ └── HandlerPerformanceWidget.php # Dashboard: bar chart per handler
|
||||
│ ├── Enums/
|
||||
│ │ ├── ContractType.php
|
||||
│ │ ├── ContractStatus.php
|
||||
│ │ ├── HandoverStatus.php
|
||||
│ │ └── ServiceType.php
|
||||
│ ├── Models/
|
||||
│ │ ├── User.php # HasRoles (Spatie), isAdmin(), isManager()
|
||||
│ │ ├── Department.php # NEW: name, manager_id → User
|
||||
@@ -101,6 +109,15 @@ minicrm/
|
||||
│ │ └── TicketClosed.php # DB + Mail for ticket closure
|
||||
│ └── Providers/Filament/
|
||||
│ └── AdminPanelProvider.php
|
||||
├── lang/ # i18n translation files
|
||||
│ ├── en/
|
||||
│ │ ├── app.php # General UI labels, navigation, status, widgets
|
||||
│ │ ├── feedback.php # Feedback domain: services, notifications, interactions
|
||||
│ │ └── enums.php # Enum labels
|
||||
│ └── vi/
|
||||
│ ├── app.php
|
||||
│ ├── feedback.php
|
||||
│ └── enums.php
|
||||
├── resources/views/filament/resources/feedback/
|
||||
│ ├── similar-cases.blade.php
|
||||
│ └── attachment-links.blade.php # Modal listing attachments with signed download URLs
|
||||
@@ -217,19 +234,84 @@ feedback_interactions, feedback_tags, feedback_feedback_tag, products, customers
|
||||
- AvgProcessingTimeWidget: 4 stats (resolved count, avg time, pending count, escalated count)
|
||||
- HandlerPerformanceWidget: bar chart of avg processing time per handler
|
||||
|
||||
## Internationalization (i18n)
|
||||
|
||||
### Configuration
|
||||
- Default locale: `vi` (Vietnamese), fallback: `en` (English)
|
||||
- Set in `.env`: `APP_LOCALE=vi`, `APP_FALLBACK_LOCALE=en`
|
||||
- Filament uses `app()->getLocale()` — no extra panel config needed
|
||||
|
||||
### Translation Files
|
||||
```
|
||||
lang/
|
||||
├── en/
|
||||
│ ├── app.php # General UI: navigation, labels, status, widgets, blade strings
|
||||
│ ├── feedback.php # Feedback domain: services, notifications, interactions
|
||||
│ └── enums.php # Enum labels (HandoverStatus, ServiceType, ContractStatus, ContractType)
|
||||
└── vi/
|
||||
├── app.php
|
||||
├── feedback.php
|
||||
└── enums.php
|
||||
```
|
||||
|
||||
### Translation Patterns
|
||||
```php
|
||||
// Resource labels — MUST override getPluralLabel() (not auto-translated)
|
||||
public static function getPluralLabel(): ?string
|
||||
{
|
||||
return __('app.resource_feedbacks');
|
||||
}
|
||||
|
||||
// Navigation group — MUST override getNavigationGroup() (not auto-translated)
|
||||
public static function getNavigationGroup(): ?string
|
||||
{
|
||||
return __('app.nav_customer_care');
|
||||
}
|
||||
|
||||
// Form fields — MUST add explicit ->label()
|
||||
TextInput::make('name')->label(__('app.name'))
|
||||
|
||||
// Status options
|
||||
'options' => [
|
||||
'pending' => __('app.status_pending'),
|
||||
'processing' => __('app.status_processing'),
|
||||
]
|
||||
|
||||
// Enum labels
|
||||
public function label(): string
|
||||
{
|
||||
return match ($this) {
|
||||
self::ACTIVE => __('enums.contract_status.active'),
|
||||
};
|
||||
}
|
||||
|
||||
// Widget heading/description — override getHeading()/getDescription()
|
||||
public function getHeading(): string | Htmlable | null
|
||||
{
|
||||
return __('app.widget_avg_time_by_handler');
|
||||
}
|
||||
```
|
||||
|
||||
### Key Gotchas
|
||||
- `$pluralLabel` property does NOT auto-translate — must override `getPluralLabel()`
|
||||
- `getNavigationGroup()` does NOT auto-translate — must call `__()` explicitly
|
||||
- `$heading`/`$description` in ChartWidget are raw properties — must override `getHeading()`/`getDescription()`
|
||||
- Form fields without `->label()` use Filament's `filament-panels::` namespace (may not resolve correctly)
|
||||
- Always add `->label(__('key'))` to TextInput, Select, Textarea, etc.
|
||||
|
||||
## Navigation Structure
|
||||
|
||||
```
|
||||
Dashboard
|
||||
├── Customer Care (group)
|
||||
│ └── Feedbacks (chat-bubble-left-right, sort=1)
|
||||
└── Management (group)
|
||||
├── Products (building-storefront, sort=1)
|
||||
├── Customers (user-group, sort=2)
|
||||
├── Channels (inbox-stack, sort=3)
|
||||
├── Tags (tag, sort=default)
|
||||
├── Users (users, sort=5) — admin only
|
||||
└── Roles (shield-check, sort=6) — admin only
|
||||
├── Customer Care / Chăm sóc khách hàng (group)
|
||||
│ └── Feedbacks / Phản ánh (chat-bubble-left-right, sort=1)
|
||||
└── Management / Quản lý (group)
|
||||
├── Products / Sản phẩm (building-storefront, sort=1)
|
||||
├── Customers / Khách hàng (user-group, sort=2)
|
||||
├── Channels / Kênh phản ánh (inbox-stack, sort=3)
|
||||
├── Tags / Thẻ (tag, sort=default)
|
||||
├── Users / Người dùng (users, sort=5) — admin only
|
||||
└── Roles / Vai trò (shield-check, sort=6) — admin only
|
||||
```
|
||||
|
||||
Dashboard widgets: ResolvedTicketsWidget, AvgProcessingTimeWidget, HandlerPerformanceWidget (admin/manager only)
|
||||
@@ -337,3 +419,8 @@ $user->assignRole('manager');
|
||||
8. **ChartWidget properties**: `$heading` and `$columnSpan` are non-static in Filament's ChartWidget.
|
||||
9. **Manager closing permission**: Manager must be department head (`Department.manager_id`) to close tickets in that department.
|
||||
10. **Docker**: Entrypoint auto-generates APP_KEY and runs migrations. SQLite persists via volume mount.
|
||||
11. **i18n - pluralLabel**: `$pluralLabel` property does NOT auto-translate — must override `getPluralLabel()` and call `__()`.
|
||||
12. **i18n - navigationGroup**: `getNavigationGroup()` does NOT auto-translate — must return `__('key')` explicitly.
|
||||
13. **i18n - ChartWidget heading**: `$heading`/`$description` are raw properties — must override `getHeading()`/`getDescription()`.
|
||||
14. **i18n - form labels**: Form fields without `->label()` use Filament's `filament-panels::` namespace — always add explicit `->label(__('key'))`.
|
||||
15. **i18n - Filament vendor**: Filament ships 57 Vietnamese translation files — auto-activated when `APP_LOCALE=vi`.
|
||||
|
||||
Reference in New Issue
Block a user