Englische Fassung der Markenseiten: Merkmale, Leistungen, Abschnitte, Showroom, Bildunterschriften
Diese Markenfelder waren nur einsprachig gespeichert und erschienen auf der englischen Seite deutsch. Neue Spalte cms_brands.field_translations (additiv) trägt die Übersetzungen je Sprache, die bisherigen Spalten bleiben die deutsche Fassung; ohne Übersetzung gilt weiter Deutsch. Marken-Editor bearbeitet die Felder über den DE/EN-Umschalter (Bilder und Rubriken bleiben sprachübergreifend). BrandTranslationsSeeder spielt die englischen Texte der vier Kernmarken ein, ohne gepflegte Übersetzungen zu überschreiben. php artisan cms:untranslated listet Inhalte, die in einer Sprache noch fehlen oder deutsch sind. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
dc31cdb401
commit
8ddc85422e
8 changed files with 982 additions and 34 deletions
|
|
@ -95,6 +95,25 @@ $loadLocaleFields = function (CmsBrand $brand, string $locale) {
|
|||
$this->originCity = $brand->getTranslation('origin_city', $locale) ?? '';
|
||||
$this->originDistance = $brand->getTranslation('origin_distance', $locale) ?? '';
|
||||
$this->originRole = $brand->getTranslation('origin_role', $locale) ?? '';
|
||||
|
||||
// Merkmale, Leistungen, Abschnitte, Showroom und Bildunterschriften: Deutsch aus den Spalten,
|
||||
// andere Sprachen aus `field_translations` – ohne Übersetzung steht der deutsche Text als Vorlage da.
|
||||
$this->showroom = (string) ($brand->localized('showroom', $locale) ?? '');
|
||||
$this->highlights = $brand->localized('highlights', $locale) ?: ['', '', ''];
|
||||
$this->services = $brand->localized('services', $locale) ?: [['title' => '', 'description' => '']];
|
||||
$this->gallery = $brand->localizedGallery($locale);
|
||||
// Absätze im Formular als Textblock: eine Leerzeile trennt sie.
|
||||
$this->sections = collect(CmsBrand::normalizeSections($brand->localized('sections', $locale)))
|
||||
->map(fn (array $s) => [
|
||||
'title' => $s['title'],
|
||||
'paragraphs' => implode("\n\n", $s['paragraphs']),
|
||||
'claim' => $s['claim'],
|
||||
'quote' => $s['quote'],
|
||||
'quote_author' => $s['quote_author'],
|
||||
'detail_title' => $s['detail']['title'] ?? '',
|
||||
'detail_paragraphs' => implode("\n\n", $s['detail']['paragraphs'] ?? []),
|
||||
])
|
||||
->all();
|
||||
};
|
||||
|
||||
$openEdit = function (int $id) {
|
||||
|
|
@ -109,24 +128,8 @@ $openEdit = function (int $id) {
|
|||
$this->logo = $brand->logo ?? '';
|
||||
$this->image = $brand->image ?? '';
|
||||
$this->website_url = $brand->website_url ?? '';
|
||||
$this->showroom = $brand->showroom ?? '';
|
||||
$this->is_published = $brand->is_published;
|
||||
$this->order = $brand->order ?? 0;
|
||||
$this->highlights = $brand->highlights ?: ['', '', ''];
|
||||
$this->services = $brand->services ?: [['title' => '', 'description' => '']];
|
||||
$this->gallery = CmsBrand::normalizeGallery($brand->gallery);
|
||||
// Absätze im Formular als Textblock: eine Leerzeile trennt sie.
|
||||
$this->sections = collect(CmsBrand::normalizeSections($brand->sections))
|
||||
->map(fn (array $s) => [
|
||||
'title' => $s['title'],
|
||||
'paragraphs' => implode("\n\n", $s['paragraphs']),
|
||||
'claim' => $s['claim'],
|
||||
'quote' => $s['quote'],
|
||||
'quote_author' => $s['quote_author'],
|
||||
'detail_title' => $s['detail']['title'] ?? '',
|
||||
'detail_paragraphs' => implode("\n\n", $s['detail']['paragraphs'] ?? []),
|
||||
])
|
||||
->all();
|
||||
|
||||
$this->loadLocaleFields($brand, $this->editLocale);
|
||||
$this->showForm = true;
|
||||
|
|
@ -248,20 +251,30 @@ $save = function () {
|
|||
$brand->logo = $this->logo ?: null;
|
||||
$brand->image = $this->image ?: null;
|
||||
$brand->website_url = $validated['website_url'] ?: null;
|
||||
$brand->showroom = $validated['showroom'] ?: null;
|
||||
$brand->setLocalized('showroom', $this->editLocale, $validated['showroom'] ?: null);
|
||||
|
||||
$brand->highlights = collect($this->highlights)
|
||||
$brand->setLocalized('highlights', $this->editLocale, collect($this->highlights)
|
||||
->map(fn ($h) => trim((string) $h))
|
||||
->filter()
|
||||
->values()
|
||||
->toArray();
|
||||
->toArray());
|
||||
|
||||
$brand->services = collect($this->services)
|
||||
$brand->setLocalized('services', $this->editLocale, collect($this->services)
|
||||
->filter(fn ($s) => ! empty($s['title']) || ! empty($s['description']))
|
||||
->values()
|
||||
->toArray();
|
||||
->toArray());
|
||||
|
||||
$brand->gallery = CmsBrand::normalizeGallery($this->gallery);
|
||||
// Bilder und Rubriken gelten für alle Sprachen; die Unterschrift gehört zur bearbeiteten Sprache.
|
||||
$gallery = CmsBrand::normalizeGallery($this->gallery);
|
||||
$captions = collect($gallery)->mapWithKeys(fn (array $item) => [$item['image'] => $item['caption']])->all();
|
||||
|
||||
if ($this->editLocale !== CmsBrand::BASE_LOCALE) {
|
||||
$baseCaptions = $brand->localized('gallery_captions', CmsBrand::BASE_LOCALE);
|
||||
$gallery = array_map(fn (array $item) => [...$item, 'caption' => (string) ($baseCaptions[$item['image']] ?? '')], $gallery);
|
||||
}
|
||||
|
||||
$brand->gallery = $gallery;
|
||||
$brand->setLocalized('gallery_captions', $this->editLocale, $captions);
|
||||
|
||||
$brand->setTranslation('widget_label', $this->editLocale, trim((string) $this->widgetLabel));
|
||||
$brand->setTranslation('cta_title', $this->editLocale, trim((string) $this->ctaTitle));
|
||||
|
|
@ -273,7 +286,7 @@ $save = function () {
|
|||
$brand->setTranslation('origin_role', $this->editLocale, trim((string) ($validated['originRole'] ?? '')));
|
||||
|
||||
// normalizeSections() nimmt die Textblöcke entgegen und trennt sie an den Leerzeilen.
|
||||
$brand->sections = CmsBrand::normalizeSections(collect($this->sections)->map(fn (array $s) => [
|
||||
$brand->setLocalized('sections', $this->editLocale, CmsBrand::normalizeSections(collect($this->sections)->map(fn (array $s) => [
|
||||
'title' => $s['title'] ?? '',
|
||||
'paragraphs' => $s['paragraphs'] ?? '',
|
||||
'claim' => $s['claim'] ?? '',
|
||||
|
|
@ -283,7 +296,7 @@ $save = function () {
|
|||
'title' => $s['detail_title'] ?? '',
|
||||
'paragraphs' => $s['detail_paragraphs'] ?? '',
|
||||
],
|
||||
])->all());
|
||||
])->all()));
|
||||
|
||||
$brand->is_published = $validated['is_published'];
|
||||
$brand->order = $validated['order'];
|
||||
|
|
@ -367,7 +380,7 @@ $cancelForm = function () {
|
|||
placeholder="Einbauschränke nach Maß." />
|
||||
</div>
|
||||
|
||||
<flux:input wire:model="showroom" label="Showroom (optional)" placeholder="Showroom Bielefeld" />
|
||||
<flux:input wire:model="showroom" label="Showroom ({{ strtoupper($editLocale) }}, optional)" placeholder="Showroom Bielefeld" />
|
||||
<flux:input wire:model="website_url" label="Herstellerseite (optional)" placeholder="https://..." />
|
||||
@error('website_url') <span class="text-sm text-red-600">{{ $message }}</span> @enderror
|
||||
|
||||
|
|
@ -403,7 +416,7 @@ $cancelForm = function () {
|
|||
{{-- Drei Merkmale für die Übersichtsseite --}}
|
||||
<div class="mt-6">
|
||||
<div class="mb-2 flex items-center justify-between">
|
||||
<flux:heading size="sm">Merkmale auf /marken</flux:heading>
|
||||
<flux:heading size="sm">Merkmale auf /marken ({{ strtoupper($editLocale) }})</flux:heading>
|
||||
<flux:button size="xs" variant="ghost" icon="plus" wire:click="addHighlight">Merkmal hinzufügen</flux:button>
|
||||
</div>
|
||||
<div class="space-y-2">
|
||||
|
|
@ -461,7 +474,7 @@ $cancelForm = function () {
|
|||
{{-- Leistungen --}}
|
||||
<div class="mt-6">
|
||||
<div class="mb-2 flex items-center justify-between">
|
||||
<flux:heading size="sm">Leistungen und Besonderheiten</flux:heading>
|
||||
<flux:heading size="sm">Leistungen und Besonderheiten ({{ strtoupper($editLocale) }})</flux:heading>
|
||||
<flux:button size="xs" variant="ghost" icon="plus" wire:click="addService">Punkt hinzufügen</flux:button>
|
||||
</div>
|
||||
<div class="space-y-4">
|
||||
|
|
@ -485,7 +498,7 @@ $cancelForm = function () {
|
|||
{{-- Abschnitte der Markenseite --}}
|
||||
<div class="mt-6">
|
||||
<div class="mb-2 flex items-center justify-between">
|
||||
<flux:heading size="sm">Abschnitte der Markenseite</flux:heading>
|
||||
<flux:heading size="sm">Abschnitte der Markenseite ({{ strtoupper($editLocale) }})</flux:heading>
|
||||
<flux:button size="xs" variant="ghost" icon="plus" wire:click="addSection">Abschnitt hinzufügen</flux:button>
|
||||
</div>
|
||||
|
||||
|
|
@ -596,7 +609,7 @@ $cancelForm = function () {
|
|||
</flux:select>
|
||||
|
||||
<flux:input wire:model="gallery.{{ $i }}.caption" size="sm" class="mb-2"
|
||||
placeholder="Bildunterschrift (optional)" />
|
||||
placeholder="Bildunterschrift {{ strtoupper($editLocale) }} (optional)" />
|
||||
|
||||
<div class="flex items-center justify-between gap-2">
|
||||
<livewire:admin.cms.media-picker :value="null" field="brand_gallery:{{ $i }}"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue