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>
105 lines
3.7 KiB
PHP
105 lines
3.7 KiB
PHP
<?php
|
||
|
||
namespace App\Console\Commands;
|
||
|
||
use App\Models\CmsArticle;
|
||
use App\Models\CmsBrand;
|
||
use FluxCms\Core\Models\CmsContent;
|
||
use Illuminate\Console\Command;
|
||
|
||
/**
|
||
* Findet Inhalte, die auf der englischen Seite deutsch erscheinen (09.10.2026): CMS-Sektionen,
|
||
* Marken (auch Merkmale, Leistungen, Abschnitte, Showroom, Bildunterschriften) und Magazin.
|
||
* Erkennung über typische deutsche Wörter – Eigennamen wie „Möbelservice“ allein schlagen nicht an.
|
||
*/
|
||
class CmsUntranslated extends Command
|
||
{
|
||
protected $signature = 'cms:untranslated {--locale=en : Zielsprache}';
|
||
|
||
protected $description = 'Listet CMS-Inhalte, die in der Zielsprache fehlen oder noch deutsch sind';
|
||
|
||
private const GermanWords = '/\b(und|der|die|das|für|mit|nicht|wir|Sie|Ihr|Ihre|Ihnen|ist|auf|ein|eine|vom|zum|zur|bei|aus|oder|auch|sich|werden|wird|unser|unsere|dem|den|des|im|sind|alle|mehr|über|wie|nach|nur|noch)\b/u';
|
||
|
||
public function handle(): int
|
||
{
|
||
$locale = (string) $this->option('locale');
|
||
$findings = [];
|
||
|
||
foreach (CmsContent::query()->orderBy('group')->orderBy('key')->get() as $row) {
|
||
$translations = $row->getTranslations('value');
|
||
$label = "CMS {$row->group}.{$row->key}";
|
||
|
||
if (! array_key_exists($locale, $translations)) {
|
||
$findings[] = [$label, 'keine Übersetzung'];
|
||
|
||
continue;
|
||
}
|
||
|
||
$this->collect($translations[$locale], $label, $findings);
|
||
}
|
||
|
||
foreach (CmsBrand::query()->ordered()->get() as $brand) {
|
||
foreach ($brand->translatable as $attribute) {
|
||
$translations = $brand->getTranslations($attribute);
|
||
|
||
if (filled($translations[CmsBrand::BASE_LOCALE] ?? null) && blank($translations[$locale] ?? null)) {
|
||
$findings[] = ["Marke {$brand->slug}.{$attribute}", 'keine Übersetzung'];
|
||
} else {
|
||
$this->collect($translations[$locale] ?? null, "Marke {$brand->slug}.{$attribute}", $findings);
|
||
}
|
||
}
|
||
|
||
foreach (CmsBrand::LOCALIZED_FIELDS as $field) {
|
||
$this->collect($brand->localized($field, $locale), "Marke {$brand->slug}.{$field}", $findings);
|
||
}
|
||
}
|
||
|
||
foreach (CmsArticle::query()->get() as $article) {
|
||
foreach ($article->translatable as $attribute) {
|
||
$translations = $article->getTranslations($attribute);
|
||
$label = "Magazin {$article->slug}.{$attribute}";
|
||
|
||
if (filled($translations[CmsBrand::BASE_LOCALE] ?? null) && blank($translations[$locale] ?? null)) {
|
||
$findings[] = [$label, 'keine Übersetzung'];
|
||
} else {
|
||
$this->collect($translations[$locale] ?? null, $label, $findings);
|
||
}
|
||
}
|
||
}
|
||
|
||
if ($findings === []) {
|
||
$this->info("Keine deutschen oder fehlenden Texte für „{$locale}“ gefunden.");
|
||
|
||
return self::SUCCESS;
|
||
}
|
||
|
||
$this->table(['Stelle', 'Text'], $findings);
|
||
$this->warn(count($findings).' Stellen.');
|
||
|
||
return self::FAILURE;
|
||
}
|
||
|
||
/**
|
||
* @param list<array{0: string, 1: string}> $findings
|
||
*/
|
||
private function collect(mixed $value, string $path, array &$findings): void
|
||
{
|
||
if (is_array($value)) {
|
||
foreach ($value as $key => $item) {
|
||
$this->collect($item, "{$path}.{$key}", $findings);
|
||
}
|
||
|
||
return;
|
||
}
|
||
|
||
if (! is_string($value)) {
|
||
return;
|
||
}
|
||
|
||
$text = trim(html_entity_decode(strip_tags($value)));
|
||
|
||
if ($text !== '' && preg_match_all(self::GermanWords, $text) >= 2) {
|
||
$findings[] = [$path, mb_strimwidth($text, 0, 90, '…')];
|
||
}
|
||
}
|
||
}
|