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
116
tests/Feature/BrandTranslationsTest.php
Normal file
116
tests/Feature/BrandTranslationsTest.php
Normal file
|
|
@ -0,0 +1,116 @@
|
|||
<?php
|
||||
|
||||
use App\Models\CmsBrand;
|
||||
use App\Models\User;
|
||||
use Database\Seeders\BrandImageSeeder;
|
||||
use Database\Seeders\BrandPageTextSeeder;
|
||||
use Database\Seeders\BrandTranslationsSeeder;
|
||||
use Database\Seeders\CmsBrandSeeder;
|
||||
use Database\Seeders\ContentCorrections20261008Seeder;
|
||||
use Database\Seeders\DemoBrandGalleryCleanupSeeder;
|
||||
use Database\Seeders\OtterpohlBrandSeeder;
|
||||
use Livewire\Volt\Volt;
|
||||
|
||||
/**
|
||||
* Englische Fassung der bisher einsprachigen Markenfelder (09.10.2026).
|
||||
*/
|
||||
function brandWithGallery(): CmsBrand
|
||||
{
|
||||
return CmsBrand::factory()->create([
|
||||
'slug' => 'muster',
|
||||
'highlights' => ['Millimetergenaue Planung'],
|
||||
'services' => [['title' => 'Aufmaß vor Ort', 'description' => 'Bei Ihnen zu Hause.']],
|
||||
'showroom' => 'Showroom Bielefeld',
|
||||
'gallery' => [
|
||||
['image' => 'a.webp', 'category' => 'inspiration', 'caption' => 'Schrank in Eiche'],
|
||||
['image' => 'b.webp', 'category' => 'project', 'caption' => 'Küche mit Insel'],
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
it('falls back to german and uses the english version where one exists', function () {
|
||||
$brand = brandWithGallery();
|
||||
$brand->setLocalized('highlights', 'en', ['Planned to the millimetre']);
|
||||
$brand->setLocalized('gallery_captions', 'en', ['a.webp' => 'Wardrobe in oak']);
|
||||
$brand->save();
|
||||
|
||||
expect($brand->localized('highlights', 'en'))->toBe(['Planned to the millimetre'])
|
||||
->and($brand->localized('highlights', 'de'))->toBe(['Millimetergenaue Planung'])
|
||||
->and($brand->localized('services', 'en'))->toBe($brand->services)
|
||||
->and(array_column($brand->localizedGallery('en'), 'caption'))->toBe(['Wardrobe in oak', 'Küche mit Insel']);
|
||||
});
|
||||
|
||||
it('does not store a translation that is just the german text', function () {
|
||||
$brand = brandWithGallery();
|
||||
$brand->setLocalized('showroom', 'en', 'Showroom Bielefeld');
|
||||
$brand->setLocalized('highlights', 'en', ['Millimetergenaue Planung']);
|
||||
$brand->save();
|
||||
|
||||
expect($brand->fresh()->field_translations)->toBeNull();
|
||||
});
|
||||
|
||||
it('edits the english fields in the brand editor without touching the german ones', function () {
|
||||
$this->actingAs(User::factory()->create());
|
||||
$brand = brandWithGallery();
|
||||
|
||||
Volt::test('admin.cms.brands-index')
|
||||
->call('openEdit', $brand->id)
|
||||
->call('switchLocale', 'en')
|
||||
->assertSet('highlights', ['Millimetergenaue Planung'])
|
||||
->set('highlights', ['Planned to the millimetre'])
|
||||
->set('services', [['title' => 'Measuring on site', 'description' => 'At your home.']])
|
||||
->set('gallery.1.caption', 'Kitchen with island')
|
||||
->set('brandName', 'Muster')
|
||||
->call('save');
|
||||
|
||||
$brand->refresh();
|
||||
|
||||
expect($brand->highlights)->toBe(['Millimetergenaue Planung'])
|
||||
->and($brand->gallery[1]['caption'])->toBe('Küche mit Insel')
|
||||
->and($brand->localized('highlights', 'en'))->toBe(['Planned to the millimetre'])
|
||||
->and($brand->localized('services', 'en')[0]['title'])->toBe('Measuring on site')
|
||||
->and(array_column($brand->localizedGallery('en'), 'caption'))->toBe(['Schrank in Eiche', 'Kitchen with island']);
|
||||
});
|
||||
|
||||
it('translates every german brand text of the four core brands and keeps maintained translations', function () {
|
||||
foreach ([CmsBrandSeeder::class, BrandPageTextSeeder::class, OtterpohlBrandSeeder::class, BrandImageSeeder::class, DemoBrandGalleryCleanupSeeder::class, ContentCorrections20261008Seeder::class] as $seeder) {
|
||||
$this->seed($seeder);
|
||||
}
|
||||
|
||||
$cabinet = CmsBrand::query()->where('slug', 'cabinet')->first();
|
||||
$cabinet->setLocalized('showroom', 'en', 'Our own showroom');
|
||||
$cabinet->save();
|
||||
|
||||
$this->seed(BrandTranslationsSeeder::class);
|
||||
$this->seed(BrandTranslationsSeeder::class);
|
||||
|
||||
foreach (CmsBrand::query()->get() as $brand) {
|
||||
foreach (['highlights', 'services', 'sections'] as $field) {
|
||||
$german = $brand->localized($field, 'de');
|
||||
$english = $brand->localized($field, 'en');
|
||||
|
||||
expect($english)->not->toBe($german, "{$brand->slug}.{$field}")
|
||||
->and(count($english ?? []))->toBe(count($german ?? []), "{$brand->slug}.{$field}");
|
||||
}
|
||||
}
|
||||
|
||||
expect($cabinet->fresh()->localized('showroom', 'en'))->toBe('Our own showroom');
|
||||
|
||||
$this->artisan('cms:untranslated')->expectsOutputToContain('Keine deutschen')->assertSuccessful();
|
||||
});
|
||||
|
||||
it('shows the english brand texts on the english website and the german ones on the german', function () {
|
||||
foreach ([CmsBrandSeeder::class, BrandPageTextSeeder::class, BrandTranslationsSeeder::class] as $seeder) {
|
||||
$this->seed($seeder);
|
||||
}
|
||||
|
||||
$this->withSession(['locale' => 'en'])->get('/marken/cabinet')->assertSuccessful()
|
||||
->assertSee('Millimetres, not standard sizes')
|
||||
->assertDontSee('Millimeter statt Standardmaß');
|
||||
|
||||
$this->withSession(['locale' => 'en'])->get('/marken')->assertSuccessful()
|
||||
->assertSee('Planned to the millimetre');
|
||||
|
||||
$this->withSession(['locale' => 'de'])->get('/marken/cabinet')->assertSuccessful()
|
||||
->assertSee('Millimeter statt Standardmaß');
|
||||
});
|
||||
Loading…
Add table
Add a link
Reference in a new issue