feat(i18n): wrap 1103 hardcoded UI strings across Filament with __()

- Convert static $modelLabel/$pluralModelLabel/$title to getter methods
- Wrap ->label()/->placeholder()/->helperText()/->description()/->title()/->body() args
- Wrap Section::make()/Fieldset::make()/Notification::make()->title() args
- Fix RelationManagers::getTitle() signature to match parent (Model, string)
- Fix Pages::getTitle() to instance method (BasePage::getTitle is non-static)
- Extend lang/ru.json + lang/en.json with 700+ common terms; identity fallback for the rest
- Remove duplicate getters in 5 resources that had manual getModelLabel already

All 306 tests pass. Missing translations fall back to the RO key so the UI never breaks.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-15 05:04:24 +00:00
parent 78ff8d4b43
commit f7fc69077b
83 changed files with 4212 additions and 1251 deletions
+27 -27
View File
@@ -46,7 +46,7 @@ class PlanResource extends Resource
public static function form(Schema $schema): Schema
{
return $schema->components([
Schemas\Components\Section::make('Identificare')
Schemas\Components\Section::make(__('Identificare'))
->columns(2)
->schema([
Forms\Components\TextInput::make('slug')
@@ -54,25 +54,25 @@ class PlanResource extends Resource
->dehydrateStateUsing(fn ($s) => strtolower((string) $s))
->extraInputAttributes(['style' => 'text-transform:lowercase']),
Forms\Components\TextInput::make('name')->required()->maxLength(60),
Forms\Components\Toggle::make('is_active')->label('Activ')->default(true),
Forms\Components\Toggle::make('is_public')->label('Public (afișat la signup)')->default(true),
Forms\Components\Toggle::make('is_active')->label(__('Activ'))->default(true),
Forms\Components\Toggle::make('is_public')->label(__('Public (afișat la signup)'))->default(true),
Forms\Components\Toggle::make('is_demo')
->label('Demo (pentru demonstrații sales)')
->helperText('Plan ascuns public, folosit pentru tenant-i demo cu features deblocate.')
->label(__('Demo (pentru demonstrații sales)'))
->helperText(__('Plan ascuns public, folosit pentru tenant-i demo cu features deblocate.'))
->default(false),
Forms\Components\TextInput::make('trial_days')
->label('Perioadă trial (zile)')
->numeric()->placeholder('null = fără trial')
->helperText('Numărul de zile gratis după ce un tenant alege acest plan.'),
->label(__('Perioadă trial (zile)'))
->numeric()->placeholder(__('null = fără trial'))
->helperText(__('Numărul de zile gratis după ce un tenant alege acest plan.')),
]),
Schemas\Components\Section::make('Preț')
Schemas\Components\Section::make(__('Preț'))
->columns(3)
->schema([
Forms\Components\TextInput::make('price_monthly')->label('Preț lunar')->numeric()->required()->suffix(fn (Get $get) => $get('currency') ?? 'MDL'),
Forms\Components\TextInput::make('price_yearly')->label('Preț anual')->numeric()->helperText('De obicei 10× preț lunar (2 luni gratis).')->suffix(fn (Get $get) => $get('currency') ?? 'MDL'),
Forms\Components\TextInput::make('price_monthly')->label(__('Preț lunar'))->numeric()->required()->suffix(fn (Get $get) => $get('currency') ?? 'MDL'),
Forms\Components\TextInput::make('price_yearly')->label(__('Preț anual'))->numeric()->helperText(__('De obicei 10× preț lunar (2 luni gratis).'))->suffix(fn (Get $get) => $get('currency') ?? 'MDL'),
Forms\Components\Select::make('currency')->options(['MDL' => 'MDL', 'EUR' => 'EUR', 'USD' => 'USD'])->default('MDL'),
]),
Schemas\Components\Section::make('Funcționalități incluse')
Schemas\Components\Section::make(__('Funcționalități incluse'))
->columns(2)
->schema([
Forms\Components\CheckboxList::make('features')
@@ -80,15 +80,15 @@ class PlanResource extends Resource
->columns(2)
->columnSpanFull(),
]),
Schemas\Components\Section::make('Limite')
Schemas\Components\Section::make(__('Limite'))
->columns(3)
->schema([
Forms\Components\TextInput::make('limits.max_users')->label('Max useri')->numeric()->placeholder('∞'),
Forms\Components\TextInput::make('limits.max_clients')->label('Max clienți')->numeric()->placeholder('∞'),
Forms\Components\TextInput::make('limits.max_vehicles')->label('Max mașini')->numeric()->placeholder('∞'),
Forms\Components\TextInput::make('limits.max_work_orders_month')->label('Max fișe/lună')->numeric()->placeholder('∞'),
Forms\Components\TextInput::make('limits.storage_mb')->label('Storage (MB)')->numeric()->placeholder('∞'),
Forms\Components\TextInput::make('limits.ai_messages_month')->label('Mesaje AI/lună')->numeric()->placeholder('∞'),
Forms\Components\TextInput::make('limits.max_users')->label(__('Max useri'))->numeric()->placeholder('∞'),
Forms\Components\TextInput::make('limits.max_clients')->label(__('Max clienți'))->numeric()->placeholder('∞'),
Forms\Components\TextInput::make('limits.max_vehicles')->label(__('Max mașini'))->numeric()->placeholder('∞'),
Forms\Components\TextInput::make('limits.max_work_orders_month')->label(__('Max fișe/lună'))->numeric()->placeholder('∞'),
Forms\Components\TextInput::make('limits.storage_mb')->label(__('Storage (MB)'))->numeric()->placeholder('∞'),
Forms\Components\TextInput::make('limits.ai_messages_month')->label(__('Mesaje AI/lună'))->numeric()->placeholder('∞'),
]),
]);
}
@@ -103,29 +103,29 @@ class PlanResource extends Resource
->description(fn ($record) => $record->is_demo ? '🎬 Demo' : ($record->trial_days ? "🎁 {$record->trial_days} zile trial" : null)),
Tables\Columns\TextColumn::make('price_monthly')
->money(fn ($record) => $record->currency)
->label('Lunar')
->label(__('Lunar'))
->sortable(),
Tables\Columns\TextColumn::make('price_yearly')
->money(fn ($record) => $record->currency)
->label('Anual'),
->label(__('Anual')),
Tables\Columns\TextColumn::make('companies_count')
->counts('companies')
->label('Abonați')
->label(__('Abonați'))
->badge()
->color('primary'),
Tables\Columns\TextColumn::make('features')
->label('Funcționalități')
->label(__('Funcționalități'))
->formatStateUsing(fn ($s) => is_array($s) ? count($s) . ' incluse' : '—')
->badge(),
Tables\Columns\IconColumn::make('is_active')->boolean()->label('Activ'),
Tables\Columns\IconColumn::make('is_public')->boolean()->label('Public'),
Tables\Columns\IconColumn::make('is_active')->boolean()->label(__('Activ')),
Tables\Columns\IconColumn::make('is_public')->boolean()->label(__('Public')),
])
->actions([
Actions\EditAction::make(),
Actions\DeleteAction::make(),
])
->emptyStateHeading('Niciun plan definit')
->emptyStateDescription('Creează planuri (ex: Free, Basic, Pro) și atribuie-le companiilor.')
->emptyStateHeading(__('Niciun plan definit'))
->emptyStateDescription(__('Creează planuri (ex: Free, Basic, Pro) și atribuie-le companiilor.'))
->defaultSort('price_monthly');
}