Commit Graph

214 Commits

Author SHA1 Message Date
Vasyka 98f71d782c i18n(payroll-runs): +8 translations + fix hardcoded notification title
Notification 'Calculat salariul YYYY-MM pentru N utilizatori' was
built via string interpolation → couldn't translate. Now uses __()
with :period / :count placeholders. Adds 7 more translations for
section titles and column labels.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-07-17 07:01:42 +00:00
Vasyka 5dcf279e62 i18n(validation): publish Laravel lang files + translate to RO and RU
- `php artisan lang:publish` created lang/en/{auth,pagination,passwords,validation}.php
- Copied to lang/ro/ and lang/ru/ and translated 30+ most-used validation
  rules (required, email, min, max, unique, exists, etc.), auth messages
  (failed, password, throttle), and pagination labels (previous/next).
- Fixes 'validation.required' literal appearing on form errors in RO/RU
  locales.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-07-17 06:59:17 +00:00
Vasyka c9d754fade i18n(employee-profiles): +9 translations for full list + create form
Section titles (Profil, Salariu & comisioane), commission column
headers (% Manopere / % marja piese), plural model label, hire date
label, and both commission helper texts.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-07-17 06:56:19 +00:00
Vasyka 74fe9fc8d9 i18n: +2 Payment::METHODS translations (Card, Virament)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-07-17 06:43:00 +00:00
Vasyka 67aa138092 i18n(expenses): add missing lowercase 'cheltuială'/'cheltuieli' model labels
Model labels used lowercase (Expense::getModelLabel returns __('cheltuială'))
but dict only had capitalised keys. Filament rendered 'Создать
Cheltuială' as fallback. Now RU shows 'Создать расход' / EN 'Create
expense'.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-07-17 06:40:40 +00:00
Vasyka 4ba003f25c i18n(payments): explicit ->label('Metodă') on method select
Field 'method' auto-generated 'Method' as label. Since RO is the source
language, __('Method') fell back to English on RO locale. Now explicitly
labeled with 'Metodă' so all 3 langs resolve properly (Metodă / Метод /
Method).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-07-17 06:36:49 +00:00
Vasyka f66227088c i18n(payments): +4 translations (model labels + helper + Mobile pay method)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-07-17 06:31:33 +00:00
Vasyka 2b56bbc35b i18n(finance): full page — tabs/periods/pnl/balance + Expense.CATEGORIES
- All 4 tabs (Overview/Cashflow/P&L/Balanță) built with __() around
  the text portion, emoji stays in code
- 4 period presets wrapped with __()
- P&L table Marjă/Marjă piese footer wrapped
- Expense::CATEGORIES values look up through __() in the expensesByCat
  loop so categories show translated (Salariu → Зарплата etc.)
- +25 translations covering all UI copy on /app/finance

306 tests pass.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-07-17 06:28:53 +00:00
Vasyka 5a2b97833a i18n(warehouses): +3 translations (Loturi, empty state)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-07-17 05:48:57 +00:00
Vasyka f45df71410 i18n(pricing-coefficients): wrap BODY_TYPES/TRANSMISSION_TYPES CheckboxList options
The two CheckboxList options passed raw Vehicle::BODY_TYPES and
Vehicle::TRANSMISSION_TYPES arrays — now they run through I18n::opts()
so the RO values translate at display. +6 translations for the enum
values that weren't yet in dict (Crossover, Pickup, Minivan, DSG,
DCT, AMT).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-07-16 20:59:33 +00:00
Vasyka 1de1812fed i18n(pricing-coefficients): +15 translations covering list + create form
Includes VEHICLE_CLASSES enum values (Sedan/Hatchback, SUV/Crossover,
Comercial, Hibrid, Electric EV, Premium/Lux), section titles
(Coeficient), badges (Prio/Cumul.), all helper texts, empty-state
heading + description, placeholder example.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-07-16 20:57:31 +00:00
Vasyka 2985c38d93 i18n(markup-rules): +11 translations + wrap key label & categories
Wrapped the dynamic Select 'key' label (Brand/Categorie) with __(),
switched the category options to I18n::opts(). Notification 'Recalculat
preț pentru N piese' now uses __(:n) placeholder.

+11 keys: regulă, reguli markup, Cheie, Mai mic = aplicat primul.,
'Va recalcula sell_price…' confirm text, notification, 'Interval preț'
enum, and missing Part.CATEGORIES (Ulei, Filtre, Lichide, Distribuție).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-07-16 20:55:13 +00:00
Vasyka 00fb4a304a feat(units): add Unit-of-measure nomenclator (per-tenant, 3 langs)
- Migration: create `units` table + nullable unit_id FK on
  parts / wo_parts / purchase_items / labor_parts. Seeds ~11 standard
  units (buc/set/l/ml/kg/g/m/cm/m²/oră/pack) for every existing
  tenant and backfills unit_id by matching the legacy string `unit`
  column. Keeps `unit` string as fallback so old code paths keep
  rendering.
- Unit model: label(locale), forSelect(locale), labelFor(id, code)
  helpers. All 4 owner models get unitModel() relation + unitLabel()
  accessor.
- UnitResource under Depozit group with Filament UI: code, sort,
  is_active + separate name_ro/name_ru/name_en fields.
- Filament forms/tables updated: Part / PurchaseItem / LaborPart /
  WorkOrderPart now use Select('unit_id')->options(Unit::forSelect())
  for input and TextColumn->getStateUsing(unitLabel()) for display.
  Selecting a part auto-fills unit_id when the source has one.
- +10 translations for the new resource + defaults; nav.label
  'Unități de măsură' added to all 3 lang files.

All 306 tests pass.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-07-16 20:52:06 +00:00
Vasyka cb8673c8a6 i18n: add 'Buy price' (Filament auto-generated from buy_price field)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-07-16 20:37:40 +00:00
Vasyka e9201c4c9a i18n(purchases+suppliers create): +13 translations for form labels & helpers
Supplier form: Categorii, Zile livrare, Net 30 / Avans placeholder,
Rerating action, Date insuficiente + helper.
Purchase form auto-generated headlines: Contact name, Pay terms,
Delivery days, Categories, Order date, Expected at, Received at.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-07-16 20:31:04 +00:00
Vasyka c864b112b5 fix(purchases): actually apply CreateAction override
Previous commit added the translation entries but the Edit call
failed silently (file-not-read guard). Now the CreateAction has
->label(__('Adaugă articol')) + ->modalHeading(__('Adaugă articol
în comandă')) so RU/EN see translated modal.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-07-16 20:27:34 +00:00
Vasyka 993b137382 i18n(purchases): +9 translations + override Items CreateAction
- +9 keys covering PurchaseResource section, item columns (Articole,
  Comandat, Progres), notifications after receipt, receipt-warehouse
  helper, OCR upload helper
- ItemsRelationManager CreateAction now has explicit label &
  modalHeading (was auto-generated 'Create Purchase Item')

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-07-16 20:27:15 +00:00
Vasyka 13454b7f1d i18n(suppliers): +4 translations for column labels
La timp 90d, Avg zile, Cheltuit 90d, Livrare (zile).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-07-16 20:21:08 +00:00
Vasyka 661101fa4a i18n(vin-search): full page translation +15 keys, wrap remaining inline text
Wrapped 3 remaining raw RO strings ('An model (estimat)', WMI error
fallback, 'Niciun rezultat pentru') and added human RU/EN for all
15 keys used on /app/vin-search.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-07-16 11:24:10 +00:00
Vasyka 2831dbd1c1 i18n(scanner): translate full page (13 keys) + wrap inline blade + JS errors
- Wrap inline blade text ('Mod recepție'), placeholder, and JS error
  messages (via @json(__(...)) so they land as JS strings).
- +13 translations covering all UI text on /app/scanner.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-07-16 11:15:12 +00:00
Vasyka b937bc8e1d i18n: add missing 'piesă' key + fix 'piese' back to nominative
'piesă' (lowercase, Part::getModelLabel()) was identity-fallback so
Filament rendered 'Редактирование Piesă' instead of 'Редактирование
запчасть'. Also 'piese' was translated to genitive ('запчастей') from
an earlier pass where it was used as a count suffix — reverted to
nominative since it's the model label proper.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-07-16 11:13:35 +00:00
Vasyka e680b2e63c i18n(parts-edit): override CreateAction, +19 translations for tabs/columns/empty
- CrossRefsRelationManager: explicit CreateAction/EditAction labels &
  modal headings (was auto-generated as 'Create Part Cross Ref')
- +19 translations for PartResource sections (Prețuri, Furnizor
  preferat), photo gallery helper, relation-tab titles (Loturi FIFO,
  Coduri cross), Batches columns (Intrat/Rămas/Preț unit.), CrossRefs
  column (Cod echivalent), all empty-state headings/descriptions on
  the 3 relation managers, Val. abbreviation.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-07-16 11:10:09 +00:00
Vasyka 9d020345ca i18n(message-templates): +4 translations (Mesaj, Subiect, helper vars, Channel)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-07-16 11:06:25 +00:00
Vasyka f7f8a67a1b i18n(service-templates/items): override CreateAction + emptyState + edit modal
Filament's default empty state used the model class name ('service
template items') and default 'Create service template item' modal
heading. Both are now explicit __() calls.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-07-16 09:50:31 +00:00
Vasyka 478811f6fc i18n(service-templates): translate remaining Labor.CATEGORIES + name placeholder
+5 keys: ITP/Climatizare/Eșapament/Altele from Labor::CATEGORIES,
'ex: Revizie completă 15.000 km' placeholder.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-07-16 08:13:40 +00:00
Vasyka c86c32c009 i18n: add 'Linii' translation (service-templates items_count column)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-07-16 08:12:09 +00:00
Vasyka 299c81146a i18n: add 'Nou tehnician' — was a hardcoded __() key on MasterResource ListMasters
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-07-16 08:10:01 +00:00
Vasyka a3b73ae941 i18n(master-create): +2 translations (Date personale, Profesie)
The 'Nou tehnician' button label is auto-generated by Filament as
'New ' + getModelLabel() = 'New ' + __('tehnician'). It picks up the
translation already in dict — on EN it shows 'New technician',
on RU 'Новый техник'.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-07-16 08:07:50 +00:00
Vasyka c16624ebe3 fix(labor-parts): actually apply modal-heading overrides
Previous commit's translation entries were added but the source change
was silently rejected by the Edit tool's file-not-read guard. Now the
CreateAction/EditAction overrides are in place; RU shows 'Добавить
запчасть по умолчанию' / 'Изменить запчасть по умолчанию' instead of
the auto-generated 'Create Labor Part'.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-07-16 08:05:47 +00:00
Vasyka c0e1644f96 i18n(labor-parts): translate CreateAction modal heading + defaults
The RelationManager Create modal was showing 'Create Labor Part' from
the model class name. Override CreateAction/EditAction with explicit
->label() + ->modalHeading() so RU/EN see translated titles.

'buc' unit default is stored in DB (raw string); added mapping so it
displays 'шт' on RU / 'pcs' on EN.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-07-16 08:05:25 +00:00
Vasyka 7ad9929d25 i18n(labor-edit): +4 translations (Mod tarifare, PRICING_MODES, Piese implicite, helper)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-07-16 07:46:07 +00:00
Vasyka e969bb9c7d i18n: wrap all formatStateUsing(fn(\$s)=>X::CONST[\$s]??\$s) with __() (21 files)
Previous sed pass only matched \$state; missed \$s and other arg-name
variants. This time the regex is arg-name-agnostic and touches 21
files across Filament resources & relation managers.

Also wraps two special cases: UserResource role-labels lookup and
LaborResource pricing_mode ternary ('Fix' | 'Pe oră').

+27 human translations for the enum values that were still identity
fallback: WorkOrderWork.STATUSES (De făcut), Purchase.STATUSES,
OnlineOrder.STATUSES, Call.DIRECTIONS/STATUSES, BodyshopJob.TYPES/
STATUSES, TireSet.SEASONS, MessageTemplate.CHANNELS,
DamagePoint.SEVERITIES, ServiceTemplateItem.KINDS.

All 306 tests pass.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-07-16 07:41:35 +00:00
Vasyka e4e63a3a09 i18n(work-order-edit): translate tab, tracking-link modal + widen for QR
- getContentTabLabel: 'ⓘ Info & antet' now goes through __()
- Tracking-client modal heading translated ('Tracking client — WO #…')
- Both 'Închide' cancel labels wrapped in __()
- Tracking modal widened to 'lg' so the QR + link input fit without overlap
- Notification 'Șablon aplicat' template built with __() so RU/EN see
  translated pieces
- +16 translations covering the QR modal, Info tab, Închide etc.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-07-16 07:35:56 +00:00
Vasyka ec25a351ad fix(work-order): actually wrap PricingCoefficient::URGENCY with I18n::opts
Previous commit added the translation entries and commit message claimed
this, but the Edit tool call failed silently (file-not-read guard) so
the source change never landed. This time it's applied.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-07-16 07:29:04 +00:00
Vasyka a24b5e76ce i18n(work-order): wrap urgency options + translate status/urgency enums
- WorkOrderResource: urgency select ->options() now goes through
  I18n::opts() so Normal/Urgent/Express translate on RU/EN
- +18 translations: work-order header helper, apply_margin helpers,
  approved-by-client label, urgency enum (Normal/Urgent/Express),
  status enum (Nou/Diagnosticare/Aprobare client/Aprobat/În lucru/
  Așteaptă piese/Gata de ridicare/Predat), pay-status enum
  (Neplătit/Parțial/Plătit).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-07-16 07:28:47 +00:00
Vasyka 6d50cef7c1 i18n(calendar): translate 'New bay' modal helper text + Nume label
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-07-16 07:21:34 +00:00
Vasyka f3d25952cc fix(finance): guard max() when byDay array is empty
max(...[]) throws ArgumentCountError. Split the intermediate array
and only call max() when it has elements. Fixes /app/finance 500
on tenants with no payments in the current period.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-07-16 07:17:10 +00:00
Vasyka d6ef62013a i18n(calendar-modal): +6 translations for New Appointment / New Bay modal
+ Pod nou, Programare nouă (title), Subiect *, Data *, Schimb ulei + filtru
(placeholder), Ex: Curte 1, Pod 4, Atelier electric (placeholder).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-07-16 07:12:16 +00:00
Vasyka f6364176ff i18n(vehicle-create): +19 translations, wrap fuel/class options with I18n::opts
- Fuel select was passing raw strings ('Diesel', 'Hybrid', 'EV', 'Electric'
  hardcoded); rewrote as DB-key => RO-label pairs run through I18n::opts
- vehicle_class select now uses I18n::opts(PricingCoefficient::VEHICLE_CLASSES)
- +19 RU/EN entries: section titles (Identificare, Tehnice), field labels
  (Marca, Kilometraj, Clasă…), helper texts, vehicle-class enum values
  (Compact/SUV/Van/Commercial/Premium/Sport/Camion/Cabrio/Motocicletă),
  fuel enum values (Motorină/Hibrid/Electric/GPL/GNC), auto-generated
  headline keys (Fuel/Engine/Gearbox/Color).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-07-16 07:08:13 +00:00
Vasyka 38e9426d47 i18n(client-edit): +12 translations for sections, options and toggle labels
Adds RU/EN for the strings still showing raw RO on /app/clients/*/edit:
Date generale, Persoană fizică, Persoană juridică, Contacte, Telefon
alternativ, Se completează automat…, Whatsapp, Viber, Telegram, Canal
marketing, Financiar.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-07-16 07:04:40 +00:00
Vasyka a966e0b2c7 i18n(calendar): translate 'h/zi', matrix howto, load legend, day-count word
- Post/mechanic meta 'h/zi' → __('h/zi') so RU shows 'ч/день', EN 'h/day'
- Wrap the 3 load-legend labels (0–5h/10, 5–8.5h/10, ≥9h/10) so 'h' → 'ч' on RU
- Split the long howto sentence so 'Pod'/'Mecanic' + 'Zile' translate
- Default fallback 'Pod 1 (default)' now uses __('Pod') + __('implicit')

Adds 5 new translations. Post NAMES themselves are DB rows (user data)
and are shown as-is — they're not translated by the app.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-07-16 06:59:45 +00:00
Vasyka 8cf14b7e00 fix: add missing App\Support\I18n class
Was created but never staged in the previous commit; deployment failed
with 'Class App\Support\I18n not found' on any page that uses the
I18n::opts() wrapper on Model::CONSTANT Select options.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-07-16 06:54:28 +00:00
Vasyka 95aeecb932 i18n: fix widget heading, translate Select options from model consts, +40 keys
- LowStockTable: rename getHeading → getTableHeading (correct Filament API)
- Global I18n::opts() helper wraps Model::CONST values in __() so
  Select dropdowns show translated status/type/season/etc. labels
- Sed-transform ->options(X::CONST), ->options(array_combine(X::A,X::A)),
  and formatStateUsing(fn($s)=>X::CONST[$s]??$s) → wrap with __()
  (58 options + 10 combines + 7 formatStateUsing across 28 files)
- CalendarBoard: all 7 day names now via __() (was missing 4)
- calendar-board.blade: fix untranslated 'săptămâna curentă', 'capacitate',
  'rata confirmare', 'mediu', 'plin', 'Pod / Zi' / 'Mecanic / Zi'
- +40 RU/EN translations (Client & Auto, Maistru / Mecanic, Programat,
  Sosit, Finalizat, Anulat, Neprezentat, days of week, calendar KPIs)

All 306 tests pass.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-07-16 06:42:16 +00:00
Vasyka 272080b274 i18n: +278 human RU/EN translations for Filament labels & UI copy
Batch pass covering the labels the user reported (Tarifare, Preț fix,
Piese impl., Specializare, Tarif/h) plus 270+ other short RO strings
that were still identity-fallback: Filament section titles, form-field
labels, table columns with explicit ->label(__()), buttons, notifications,
placeholders, helper texts, empty-state messages.

Down from ~514 to ~253 remaining identity-fallback RO strings — the rest
are mostly long help-text paragraphs which are lower priority.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-07-16 05:32:45 +00:00
Vasyka 38650da875 fix(i18n): auto-translate labels on Filament columns/fields/filters/actions
Root cause of untranslated table headers: Filament's HasLabel::getLabel()
auto-generates a label from the field name (e.g. `name` → "Name") but only
calls __() on it if you also invoke ->translateLabel(). Without that, the
auto-generated label always renders in English regardless of app locale.

Fix: configureUsing() in AppServiceProvider makes translateLabel() the
default for every Column, BaseFilter, Field, Action and BulkAction.

Then added 175 human RU/EN translations for Filament's auto-generated
keys (Name, Phone, Email, Status, Balance, Created at, Plate, Make,
Model, Year, VIN, Mileage, Owner, Client, Vehicle, Amount, Total, Qty,
Actions, Search, Filter, Export, Import, plus enums/relationships).

All 306 tests pass. Deploy will fix table headers on
Clients / Vehicles / Work orders / Payments / Purchases / Suppliers etc.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-07-16 05:21:29 +00:00
Vasyka 7077fff3b3 feat(i18n): convert 38 hardcoded static labels + safe blade wrap + 226 keys
- Convert all remaining static \$modelLabel/\$pluralModelLabel to getter
  methods with __() (AppointmentResource, WorkOrderResource, MasterResource,
  ServiceTemplateResource, LaborResource, and 33 others)
- Safe blade wrap v2 (37 files, 201 wraps): fixed the regex to not match
  `->`, `=>`, `!<` — previous aggressive pass broke @if directives
- Bulk-translate lowercase model-label keys (programări, fișe lucru,
  tehnicieni, șabloane servicii, norme-ore, etc.) — these were the RO
  strings appearing in page titles/breadcrumbs
- Add human RU/EN for mechanic-kpi (Mecanic/Lucrări/Norma ore/etc.)
  and calendar-board words

Tests 306 green. Blade compiles cleanly.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-07-15 06:17:10 +00:00
Vasyka 3911012c65 feat(i18n): mega-wrap 494 raw RO strings + 269 lang entries + 161 human RU/163 EN
Broad sweep across the whole codebase:
- Blade views (39 files, 315 wraps): tag-text and title/placeholder/alt
  attributes wrapped with {{ __() }}. Excludes scripts, styles, @php,
  @verbatim, {{ }}, {!! !!}, comments to avoid touching interpolations.
- PHP (54 files, 179 wraps): array 'key' => 'RO value' patterns and
  list items with diacritics wrapped with __(). Reverted __() inside
  const arrays (PHP disallows non-constant expressions).
- Added 269 new keys to lang/{ru,en}.json (identity fallback for
  unknowns → 161 human RU + 163 EN translations added for the most
  common enums, stages, roles, statuses, payment methods, vehicle
  categories, warehouse, portal, form actions.

Missing translations fall back to RO so the UI never breaks. All 306
tests pass; view cache compiles cleanly.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-07-15 05:53:22 +00:00
Vasyka 2d447e6294 feat(i18n): fix widgets, pipeline & mechanic boards + missing translations
Follow-up to previous i18n pass — user reported many visible RO strings on
EN/RU locales because auto-wrap missed:
  - Stat::make() first-arg labels in StatsOverview, FinanceOverview, PlatformStats
  - $heading static in LowStockTable (converted to getHeading() method)
  - Pipeline board Blade view: 40+ literal strings wrapped with {{ __() }}
  - Mechanic board Blade view: statuses, buttons, block modal
  - PipelineBoard.php hardcoded tag labels, stage labels, notify strings
  - MechanicBoard.php confirmBlock notification

Added human RU + EN translations for the visible strings shown in the
screenshots (dashboard widgets, Client/Vehicle list breadcrumbs & columns,
pipeline board topbar/stats/filters/cards/detail panel/quick actions,
mechanic board stats/statuses/block modal). All 306 tests pass.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-07-15 05:31:26 +00:00
Vasyka f7fc69077b 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>
2026-07-15 05:04:24 +00:00
Vasyka 78ff8d4b43 feat: i18n on Filament admin sidebar — 54 resources/pages translated
User screenshots showed the tenant admin panel (Filament) had sidebar
labels stuck in Romanian even when switching to Russian: 'Cereri',
'Calendar vizual', 'Atelierul meu', 'KPI mecanici', 'Fișe lucru',
'Norme-ore', 'Tehnicieni', 'Șabloane servicii', 'Depozite', 'Scaner',
'Depozit', 'VIN-căutare', 'Furnizori', 'Achiziții', 'Procentaj',
'Coeficienți preț', plus all group headers.

Root cause: every Filament Resource and Page had static properties
'protected static ?string $navigationLabel = "Fișe lucru"' — string
literals baked into class definitions. Static properties don't run
through the translation layer.

Fix in two parts:

1. New translation files with 52 label keys + 12 group keys:
   - lang/ro/nav.php — Romanian (identity)
   - lang/ru/nav.php — full Russian translations (Заказ-наряды,
     Автомобили, Клиенты, Календарь, Моя мастерская, Механики KPI,
     Настройки, etc.)
   - lang/en/nav.php — English translations (Work orders, Vehicles,
     Clients, Calendar, My workshop, Mechanic KPI, Settings, etc.)

   Keyed by the Romanian original so lookups map 1:1 —
   'nav.label.Fișe lucru' returns 'Заказ-наряды' in RU, 'Work orders'
   in EN, 'Fișe lucru' in RO.

2. Python transformer converted 54 files:
   - 33 Filament Tenant Resources
   - 15 Filament Tenant Pages
   - 4 Filament Central Resources
   - 1 Filament Central Page
   - 1 Widget

   Each 'protected static ?string $navigationLabel = "X";' became
   'public static function getNavigationLabel(): string { return
   __("nav.label.X"); }'. Same treatment for $navigationGroup.

Cleanup: 6 resources already had manually-added getNavigationLabel
methods from an earlier partial effort — those used flat JSON keys
(__("Cereri")) that never resolved. Deduped so only the nav.label.*
version remains.

Untouched (intentional):
- $modelLabel / $pluralModelLabel (used in breadcrumbs and headings —
  still hardcoded, next tier of work)
- Section titles, column headers, form field labels (medium priority)
- $navigationSort (numeric, no translation needed)
- $navigationIcon (icon reference)

Suite: 306 passed (853 assertions). Unchanged.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-07-13 20:41:55 +00:00