b2in/app/Console/Commands/CmsUntranslated.php
Kevin Adametz 8ddc85422e 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>
2026-10-09 10:08:03 +00:00

105 lines
3.7 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?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, '…')];
}
}
}