Feature: Adding Spatie's Translation Loader

This commit is contained in:
2026-08-06 00:13:13 +03:00
parent 93469d033f
commit 8646dca16a
4 changed files with 135 additions and 2 deletions
+62
View File
@@ -88,3 +88,65 @@ If a shop has only one row in `languages`, the middleware still enforces the pre
URL under `/en/...`) rather than special-casing it away — this keeps behavior identical across
shops and avoids a silent restructuring if a second language is added later. If a shop genuinely
never wants locale prefixes, don't apply the `locale` middleware to its routes at all.
---
## Storefront UI labels (`__('storefront.*')`)
The `locale` middleware resolves *which* language a request is in — routing/redirects,
`Lunar\Models\Language`, and Lunar's own translatable product/collection content. It has nothing
to do with static UI chrome like "Cart", "Back", "Add to Cart". Those are handled separately by
[`spatie/laravel-translation-loader`](https://github.com/spatie/laravel-translation-loader),
stored in the `language_lines` table.
### Why a separate system, not another `languages`-table lookup
Lunar's translatable fields (`TranslatedText`, `Url`, etc.) are all tied to specific *model
records* — a product's name, a collection's description. UI labels aren't attached to any model;
they're static strings the app itself owns. `laravel-translation-loader` is Laravel's own
`__()`/`trans()` mechanism with a DB-backed source layered on top of the normal file-based one —
no new helper to learn, no bespoke table shape.
**Nothing existing breaks.** The package's `TranslationLoaderManager` *extends* Laravel's
`FileLoader` and merges DB translations on top of file-based ones
(`array_replace_recursive()`) — Filament's own vendor `lang/en/product.php`-style strings
keep working exactly as before. The package registers itself via Laravel's standard Composer
package auto-discovery (`extra.laravel.providers` in its own `composer.json`) — nothing needed
in `CoreServiceProvider` to wire it up.
### Usage
```blade
{{ __('storefront.nav.cart') }}
{{ __('storefront.product.add_to_cart') }}
```
`group` is `storefront` for e-shop UI labels — kept separate from Lunar/Filament's own `lunar::`
namespaced groups so nothing collides. `__()` resolves the translation for whatever
`App::getLocale()` currently is, which `LocaleMiddleware` already sets per-request (see
"Behavior" above) — no extra wiring needed between the two systems.
### Seeding
A starter set of common e-shop labels (`nav.*`, `cart.*`, `product.*`, `auth.*`, `search.*`,
English + Greek) is seeded by `Modules\Core\Command\InstallLunarCommand` (overrides Lunar's own
`lunar:install`), guarded by `LanguageLine::where('group', 'storefront')->exists()` — same
idempotent pattern as the rest of that command, safe to run unattended on every boot.
**Editing existing labels or adding new ones is a normal Eloquent operation**, not a
re-seed:
```php
use Spatie\TranslationLoader\LanguageLine;
LanguageLine::create([
'group' => 'storefront',
'key' => 'nav.wishlist',
'text' => ['en' => 'Wishlist', 'el' => 'Λίστα Επιθυμιών'],
]);
```
There is currently no Filament resource for editing `language_lines` — labels are edited via
tinker/seeder until one is built. `LanguageLine` caches per group+locale
(`Cache::rememberForever`) and flushes itself automatically on `saved`/`deleted`, so edits take
effect immediately with no manual cache-clear step.