Sprog - Keywords: Platzhalter, Wildcard, Übersetzung, Translation, Mehrsprachigkeit, i18n, Sprachbasis, Filter

Übersicht

Sprog ist das Sprach-Addon für REDAXO und ermöglicht die Verwaltung von Platzhaltern (Wildcards) für Übersetzungen. Das Addon unterstützt Sprachbasen, Filter, automatische Synchronisierung von Struktur-Metadaten sowie das Kopieren von Inhalten zwischen Sprachen.

Autor: Thomas Blum
GitHub: https://github.com/tbaddade/redaxo_sprog
Abhängigkeiten: REDAXO >= 5.17
Empfohlen: YForm, Structure/Content-Plugin


Kern-Klassen

Klasse Beschreibung
Sprog\Wildcard Haupt-Klasse für Platzhalter-Verwaltung und -Ersetzung
Sprog\Abbreviation Abkürzungen mit <abbr>-Tag
Sprog\Extension Extension Points für Synchronisierung
Sprog\Sync Synchronisierung von Artikel- und Kategorie-Metadaten

Sprog\Wildcard

Methode Beschreibung
get($wildcard, $clang_id = null) Gibt übersetzten Platzhalter zurück
parse($content, $clang_id = null) Ersetzt alle Platzhalter im Content
getOpenTag() Gibt öffnendes Tag zurück (default: ``)
getRegexp($value = '.*?') Gibt RegEx-Pattern für Platzhalter zurück
isClangSwitchMode() Prüft, ob Sprach-Umschaltmodus aktiv
getMissingWildcards() Findet fehlende Platzhalter in Slices
getMissingWildcardsAsTable() Gibt fehlende Platzhalter als HTML-Tabelle zurück

Sprog\Abbreviation

Methode Beschreibung
parse($content, $clang_id = null) Ersetzt Abkürzungen mit <abbr>-Tag

Sprog\Sync

Methode Beschreibung
articleNameToCategoryName($params) Synchronisiert Artikelname → Kategoriename
categoryNameToArticleName($params) Synchronisiert Kategoriename → Artikelname
articleStatus($params) Synchronisiert Artikel-Status zwischen Sprachen
categoryStatus($params) Synchronisiert Kategorie-Status zwischen Sprachen
articleTemplate($params) Synchronisiert Template zwischen Sprachen
categoryTemplate($params) Synchronisiert Kategorie-Template zwischen Sprachen

Datenbank-Tabellen

rex_sprog_wildcard

Spalte Typ Beschreibung
pid int Primärschlüssel (Auto-Increment)
id int Platzhalter-ID (gleich für alle Sprachen)
clang_id int Sprach-ID
wildcard varchar(255) Platzhalter-Name (ohne Tags)
replace text Übersetzung
createdate datetime Erstellt am
updatedate datetime Aktualisiert am
createuser varchar(255) Erstellt von
updateuser varchar(255) Aktualisiert von
revision int Versions-Nummer

rex_sprog_abbreviation

Spalte Typ Beschreibung
id int Primärschlüssel
clang_id int Sprach-ID
abbreviation varchar(255) Abkürzung
text text Ausgeschriebener Text
status tinyint(1) Status (aktiv/inaktiv)
createdate datetime Erstellt am
updatedate datetime Aktualisiert am

Wildcard-Modus

Sprog bietet zwei Modi für die Platzhalter-Verwaltung:

Clang-Switch-Modus (Standard)

  • Separate Backend-Ansicht pro Sprache
  • Alle Sprachen haben dieselbe id, nur unterschiedliche clang_id
  • Platzhalter-Name kann nur in Admin-Ansicht geändert werden
  • Empfohlen für die meisten Projekte

Clang-All-Modus

  • Eine Tabelle zeigt alle Sprachen auf einmal
  • Alle Felder direkt editierbar
  • Übersichtlicher bei wenigen Sprachen
  • Aktivieren unter: System → Sprog → Einstellungen

30 Praxisbeispiele

1. Einfacher Platzhalter ausgeben

echo Wildcard::get('hello');
// Ausgabe: Hallo (in DE)
// Ausgabe: Hello (in EN)

2. Platzhalter mit Helper-Funktion

echo sprogcard('company_name');
// Kurzform für: Wildcard::get('company_name')

3. Text mit mehreren Platzhaltern

$text = ', ! ';
echo Wildcard::parse($text);

4. Platzhalter für spezifische Sprache

// Deutsches Impressum
$imprintDE = Wildcard::get('imprint', 1);

// Englisches Impressum
$imprintEN = Wildcard::get('imprint', 2);

5. Template mit Platzhaltern

<!DOCTYPE html>
<html lang="<?= rex_clang::getCurrent()->getCode() ?>">
<head>
    <title><?= Wildcard::get('page_title') ?></title>
    <meta name="description" content="<?= Wildcard::get('meta_description') ?>">
</head>
<body>
    <h1><?= Wildcard::get('headline') ?></h1>
    <?= $this->getArticle() ?>
    <footer>
        <p><?= Wildcard::get('copyright') ?></p>
    </footer>
</body>
</html>

6. Platzhalter mit HTML

// Backend: Platzhalter "footer_text"
// Eingabe: <p>© 2025 <strong>Meine Firma</strong></p>

// Frontend
echo Wildcard::get('footer_text');
// Ausgabe: <p>© 2025 <strong>Meine Firma</strong></p>

7. Platzhalter mit Filter (lowercase)

// 
$text = '';
echo Wildcard::parse($text);
// Ausgabe: musterfirma gmbh (statt Musterfirma GmbH)

8. Platzhalter mit Filter (uppercase)

// 
echo sprogdown('');
// Ausgabe: WILLKOMMEN

9. Platzhalter mit Filter (markdown)

// 
// Wandelt Markdown in HTML um
$text = sprogdown('');

10. Custom Filter registrieren

// boot.php
rex_extension::register('SPROG_FILTER', function(rex_extension_point $ep) {
    $filters = $ep->getSubject();
    
    $filters['uppercase'] = function($value) {
        return mb_strtoupper($value);
    };
    
    $filters['excerpt'] = function($value, $length = 100) {
        return mb_substr(strip_tags($value), 0, $length) . '...';
    };
    
    return $filters;
});

11. Filter mit Parametern

// 
// Kürzt Text auf 50 Zeichen
echo sprogdown('');

12. Sprachfeld-Helper (sprogfield)

// Statt:
$name_de = $item->getValue('name_1');
$name_en = $item->getValue('name_2');

// Besser:
$name = $item->getValue(sprogfield('name'));
// Automatisch: name_1 bei clang_id=1, name_2 bei clang_id=2

13. Sprogfield in YOrm-Dataset

class MyDataset extends \rex_yform_manager_dataset
{
    public function getName()
    {
        return trim($this->{sprogfield('name')});
    }
    
    public function getDescription()
    {
        return $this->{sprogfield('description')};
    }
}

14. Sprogvalue-Helper

$data = [
    'title_1' => 'Deutscher Titel',
    'title_2' => 'English Title',
    'text_1' => 'Deutscher Text',
    'text_2' => 'English Text'
];

// Gibt Wert für aktuelle Sprache zurück
$title = sprogvalue($data, 'title');
$text = sprogvalue($data, 'text');

15. Sprogarray-Helper

$data = [
    'title_1' => 'DE Titel',
    'title_2' => 'EN Title',
    'text_1' => 'DE Text',
    'text_2' => 'EN Text',
    'author' => 'Max Mustermann' // Kein Sprachfeld
];

// Fügt Felder ohne Suffix hinzu
$data = sprogarray($data, ['title', 'text']);

// Jetzt verfügbar:
// $data['title'] => aktueller Titel (abhängig von clang_id)
// $data['text'] => aktueller Text

16. Synchronisation: Artikelname → Kategoriename

// boot.php oder Project-Addon
rex_config::set('sprog', 'sync_structure_article_name_to_category_name', true);

// Bei Artikel-Speicherung wird Kategoriename automatisch aktualisiert

17. Synchronisation: Status zwischen Sprachen

rex_config::set('sprog', 'sync_structure_status', true);

// Artikel in DE auf "online" setzen → auch in EN "online"

18. Synchronisation: Template zwischen Sprachen

rex_config::set('sprog', 'sync_structure_template', true);

// Template-Änderung in DE → automatisch in allen Sprachen

19. Sprachbasis definieren

// Backend: System → Sprog → Einstellungen
// Sprachbasis für EN: DE (1)

// Platzhalter "hello" nur in DE gepflegt
// EN nutzt automatisch DE-Version, wenn kein EN-Wert vorhanden
$clangBase = rex_config::get('sprog', 'clang_base');
// ['1' => 1, '2' => 1] -> EN (2) nutzt DE (1) als Basis

20. Fehlende Platzhalter finden

// Backend: Sprog → Platzhalter
// Am Ende der Seite: "Fehlende Platzhalter"
// Zeigt alle  aus Slices, die noch nicht angelegt sind
$missing = Wildcard::getMissingWildcards();
dump($missing);

21. Platzhalter-Tags anpassen

// package.yml oder boot.php
rex_config::set('sprog', 'wildcard_open_tag', '[[');
rex_config::set('sprog', 'wildcard_close_tag', ']]');

// Jetzt: [[ hello ]] statt 

22. Inhalte von Sprache A nach B kopieren

// Backend: Sprog → Inhalte kopieren → Struktur & Inhalte
// Quelle: Deutsch (1)
// Ziel: Englisch (2)
// → Kopiert alle Slices von DE nach EN

23. Metadaten synchronisieren

// Backend: Sprog → Inhalte kopieren → Struktur-Metadaten
// Synchronisiert: Name, Kategorie-Name, Prio, Status, Template
// Nützlich nach großen Struktur-Änderungen in einer Sprache

24. Platzhalter exportieren (CSV)

// Backend: Sprog → Import/Export → Export
// Erzeugt CSV mit Spalten: wildcard, de, en, fr, ...
// Für Übersetzungsbüros

25. Platzhalter importieren (CSV)

// Backend: Sprog → Import/Export → Import
// CSV hochladen
// Automatische Sprach-Erkennung via Language-Code (de, en, fr)
// Optional: Fehlende Sprachen automatisch anlegen

26. Extension Point: Wildcard-Ersetzung anpassen

rex_extension::register('OUTPUT_FILTER', function($ep) {
    $content = $ep->getSubject();
    
    // Eigene Logik vor Sprog
    $content = str_replace('[[CUSTOM]]', 'Custom Value', $content);
    
    // Sprog-Wildcards ersetzen
    $content = Wildcard::parse($content);
    
    return $content;
});

27. Abbreviations (Abkürzungen)

// Backend: Sprog → Abbreviations
// Abkürzung: REDAXO
// Text: REDAXO Content Management System
// Status: Aktiv

// Frontend (automatisch via Extension Point):
// REDAXO -> <abbr title="REDAXO Content Management System">REDAXO</abbr>

28. Wildcard in REX_VALUE

// Modul OUTPUT
$text = 'REX_VALUE[1]';
$text = Wildcard::parse($text);
echo $text;

// Ermöglicht Redakteuren Platzhalter zu nutzen:
// Eingabe: Willkommen bei 
// Ausgabe: Willkommen bei Musterfirma GmbH

29. Platzhalter in YForm-Formularen

// YForm Pipe-Schreibweise
text|name|

// PHP-Schreibweise
$yform->setValueField('text', [
    'name',
    Wildcard::get('form_label_name')
]);

30. Clang-Switch deaktivieren (Alle Sprachen in einer Tabelle)

// Backend: System → Sprog → Einstellungen
// "Sprachen pro Unterseite anzeigen" deaktivieren

// Alternative via boot.php:
rex_config::set('sprog', 'wildcard_clang_switch', false);

// Jetzt: Backend → Sprog → Platzhalter
// Zeigt Tabelle mit allen Sprachen auf einmal

Konfiguration

Config-Key Typ Beschreibung Default
wildcard_open_tag string Öffnendes Platzhalter-Tag '
wildcard_close_tag string Schließendes Platzhalter-Tag '
wildcard_clang_switch bool Sprach-Umschaltmodus aktiv true
clang_base array Sprachbasen-Zuordnung (clang_id => basis_clang_id) []
sync_structure_article_name_to_category_name bool Artikelname → Kategoriename sync false
sync_structure_category_name_to_article_name bool Kategoriename → Artikelname sync false
sync_structure_status bool Status zwischen Sprachen sync false
sync_structure_template bool Template zwischen Sprachen sync false

Backend-Seiten

  1. Sprog → Platzhalter: Verwaltung aller Wildcards (Clang-Switch oder All-Modus)
  2. Sprog → Abbreviations: Verwaltung von Abkürzungen
  3. Sprog → Inhalte kopieren:
    • Struktur & Inhalte: Slices von Sprache A nach B kopieren
    • Struktur-Metadaten: Metadaten synchronisieren
  4. Sprog → Import/Export:
    • Export: CSV-Export aller Wildcards
    • Import: CSV-Import mit automatischer Sprach-Erkennung
  5. System → Sprog: Einstellungen (Tags, Clang-Switch, Sync-Optionen)

Filter

Standard-Filter

Filter Beschreibung Beispiel
lowercase Kleinbuchstaben ``
uppercase Großbuchstaben ``
markdown Markdown → HTML `<h1 id="speed-up---performance-optimierung">Speed Up - Performance-Optimierung</h1>

Keywords: Speed, Performance, Prefetch, Preload, Cache, Tracking, Hover, Assets

Übersicht

Speed Up optimiert die wahrgenommene Ladezeit durch Prefetching (nächste Seiten vorladen), Preloading (kritische Ressourcen) und Cache-Busting.

Kern-Klassen

Klasse Beschreibung
speed_up Prefetch-URLs generieren, Output erzeugen
speed_up_tracking Beliebtheit-basiertes Prefetching
speed_up_asset Assets mit Timestamp (Cache-Buster)
speed_up_theme Theme-Assets mit Timestamp
speed_up_expires_checker Expires-Header-Prüfung

Klasse: speed_up

Wichtige Methoden

Methode Rückgabe Beschreibung
::getConfig($key) mixed Config-Wert abrufen
getUrls() self URLs generieren (Nachbarn, Kinder, Popular)
getOutput() string <link rel="prefetch"> Tags
showOutput() void Output direkt ausgeben

Klasse: speed_up_tracking

Wichtige Methoden

Methode Parameter Rückgabe Beschreibung
::track($url_from, $url_to, $article_id_from, $clang_id_from, $article_id_to, $clang_id_to) string, string, ?int, ?int, ?int, ?int void Seitenübergang speichern
::getTopUrls($url_from, $limit) string, int array Top-3 häufigste Ziel-URLs
::deleteByArticle($article_id, $clang_id) int, int void Tracking für Artikel löschen
::cleanupOldEntries($maxEntriesPerUrl) int void Alte Einträge begrenzen (max 255 pro URL)

Klasse: speed_up_asset

Wichtige Methoden

Methode Parameter Rückgabe Beschreibung
::getUrl($file, $show_timestamp) string, bool string URL mit Timestamp
::getScript($file, $show_timestamp) string, bool string <script> Tag
::getLink($file, $show_timestamp, $attributes) string, bool, array string <link> Tag

Klasse: speed_up_theme

Wichtige Methoden

Methode Parameter Rückgabe Beschreibung
::getUrl($file, $show_timestamp) string, bool string Theme-Asset-URL mit Timestamp
::getScript($file, $show_timestamp) string, bool string <script> für Theme
::getLink($file, $show_timestamp, $attributes) string, bool, array string <link> für Theme

Profile

Profil Beschreibung
disabled Keine Ausgabe
custom Nur manuelle Codes + EP
auto (Standard) Startseite, 2 Nachbarn, 2 Artikel, 1 Kind-Kategorie
aggressive Alle Nachbarn, alle Artikel, alle Kinder

Praxisbeispiele

1. Automatische Einbindung

// In Einstellungen aktivieren: "Automatisch einbinden"
// Dann in Template HEAD-Bereich nichts weiter nötig

2. Manuelle Einbindung

<?php if (rex::isFrontend()): ?>
    REX_SPEED_UP[]
<?php endif; ?>

3. Profil setzen

// Backend: System > Speed Up! > Einstellungen
rex_config::set('speed_up', 'profile', 'auto');

4. Zusätzliches Prefetching

// Backend: Zusätzliches Prefetching-Feld
<link rel="prefetch" href="/wichtige-seite/">
<link rel="prefetch" href="/kontakt/">

5. Zusätzliches Preloading

// Backend: Zusätzliches Preloading-Feld
<link rel="preload" href="/assets/fonts/font.woff2" as="font" type="font/woff2" crossorigin>
<link rel="preload" href="/media/hero.jpg" as="image">

6. Webfont preloaden

<link rel="preload" href="<?= speed_up_asset::getUrl('fonts/font.woff2') ?>" as="font" type="font/woff2" crossorigin>

7. CSS/JS mit Cache-Busting

<script src="<?= speed_up_asset::getUrl('project/js/script.js') ?>"></script>
<link href="<?= speed_up_asset::getUrl('project/css/style.css') ?>" rel="stylesheet">

8. Verkürzte Schreibweise

<?= speed_up_asset::getScript('project/js/script.js') ?>
<?= speed_up_asset::getLink('project/css/style.css') ?>

9. Mit Attributen

<?= speed_up_asset::getLink('project/css/print.css', true, ['media' => 'print']) ?>
<?= speed_up_asset::getLink('project/css/custom.css', true, ['rel' => 'preload', 'as' => 'style']) ?>

10. Theme-Assets

<script src="<?= speed_up_theme::getUrl('frontend/js/app.js') ?>"></script>
<link href="<?= speed_up_theme::getUrl('frontend/css/styles.css') ?>" rel="stylesheet">

11. Theme verkürzt

<?= speed_up_theme::getScript('frontend/js/app.js') ?>
<?= speed_up_theme::getLink('frontend/css/styles.css') ?>

12. Beliebtheit-basiertes Prefetching

// Backend: "Beliebtheit-basiertes Prefetching aktivieren"
// Trackt automatisch, fügt Top-3 häufigste Ziele hinzu

13. Tracking manuell aufrufen

use speed_up_tracking;

speed_up_tracking::track(
    '/seite-a/',
    '/seite-b/',
    10, // article_id_from
    1,  // clang_id_from
    20, // article_id_to
    1   // clang_id_to
);

14. Top-URLs abrufen

$topUrls = speed_up_tracking::getTopUrls('/seite-a/', 3);
foreach ($topUrls as $url) {
    echo '<link rel="prefetch" href="' . $url . '">';
}

15. Tracking bereinigen

// Behält nur 255 neueste Einträge pro URL
speed_up_tracking::cleanupOldEntries(255);

16. Hover-basiertes Prefetching

// Backend: "Hover-basiertes Prefetching" aktivieren
// JavaScript lädt Seiten bei Hover/Touch/Focus

17. Extension Point PREFETCH_URLS

rex_extension::register('PREFETCH_URLS', function(\rex_extension_point $ep) {
    $urls = $ep->getSubject();
    
    // Eigene URLs hinzufügen
    $urls[] = '/spezial-seite/';
    
    return $urls;
});

18. Artikel vom Prefetching ausschließen

// Backend: System > Speed Up! > Artikel
// Checkbox pro Artikel: "Prefetching deaktivieren"

19. REX_VAR verwenden

<script src="REX_VAR_SPEED_UP_ASSET[file='project/js/script.js']"></script>

20. Expires-Header prüfen

// Backend: System > Speed Up! > Einstellungen
// Button: "Expires-Header prüfen"
// Zeigt Status für CSS/JS/Bilder/Fonts

21. YCom-Seiten ausschließen

// Automatisch: Login, Logout, Registrierung, Passwort-Reset
// Werden nicht geprefetcht

22. Programmatisch URLs generieren

$speedup = new speed_up();
$speedup->getUrls();
echo $speedup->getOutput();

23. Custom Profil

rex_config::set('speed_up', 'profile', 'custom');

rex_extension::register('PREFETCH_URLS', function($ep) {
    return ['/seite1/', '/seite2/', '/seite3/'];
});

24. Medienpool-Bilder preloaden

// Backend: "Medienpool-Dateien für Preloading"
// Wähle Hero-Image, Logo etc.

25. Cache-Busting ohne Timestamp

$url = speed_up_asset::getUrl('project/js/script.js', false);
// Liefert /assets/project/js/script.js (ohne ?timestamp=...)

Integration: Speed Up arbeitet mit YRewrite (Domains, Artikel-URLs), Structure (Nachbarn, Kategorien), YCom (Login-Seiten ausschließen), URL-Addon (Profile-URLs), Media Manager (Bild-Prefetching) und nutzt rex_extension (PREFETCH_URLS) für Anpassungen. JavaScript-Modul für Hover-Prefetch unterstützt Touch-Geräte und Barrierefreiheit.

` |

Custom Filter erstellen

// boot.php
rex_extension::register('SPROG_FILTER', function($ep) {
    $filters = $ep->getSubject();
    
    // Neuer Filter
    $filters['truncate'] = function($value, $length = 100, $suffix = '...') {
        if (mb_strlen($value) > $length) {
            return mb_substr($value, 0, $length) . $suffix;
        }
        return $value;
    };
    
    return $filters;
});

// Verwendung
echo sprogdown('');

Sprachbasis-System

Konzept

  • Eine Sprache (z.B. EN) kann eine andere (z.B. DE) als “Basis” definieren
  • Fehlt in EN ein Platzhalter-Wert, wird automatisch DE verwendet
  • Spart Pflegeaufwand bei redundanten Übersetzungen

Einrichtung

// Backend: System → Sprog → Einstellungen → Sprachbasis
// Für Sprache "EN (2)": Wähle "DE (1)"

// Programmatisch:
rex_config::set('sprog', 'clang_base', [
    2 => 1,  // EN nutzt DE als Basis
    3 => 1   // FR nutzt DE als Basis
]);

Beispiel

// Platzhalter "contact_phone" nur in DE gepflegt
// DE: +49 123 456789
// EN: (leer)

// Frontend in EN:
echo Wildcard::get('contact_phone', 2);
// Ausgabe: +49 123 456789 (Fallback auf DE)

CSV-Import/Export

Export-Format

wildcard,de,en,fr
company_name,Musterfirma GmbH,Sample Company Ltd,Société Exemple
contact_email,info@beispiel.de,info@example.com,info@exemple.fr

Import-Optionen

  • Fehlende Sprachen hinzufügen: Erstellt automatisch neue Sprachen aus CSV-Spalten
  • Fehlende Sprachen ignorieren: Überspringt unbekannte Sprachcodes

Extension Points

Extension Point Beschreibung
SPROG_FILTER Custom Filter registrieren
ART_UPDATED Artikel-Synchronisierung (via Sprog\Extension)
CAT_UPDATED Kategorie-Synchronisierung (via Sprog\Extension)
CLANG_ADDED Neue Sprache: Wildcards aus Startsprache kopieren
CLANG_DELETED Wildcards der gelöschten Sprache entfernen
OUTPUT_FILTER Wildcard-Ersetzung im Frontend

Helper-Funktionen

Funktion Beschreibung
sprogcard($wildcard, $clang_id = null) Kurzform für Wildcard::get()
sprogdown($text, $clang_id = null) Kurzform für Wildcard::parse()
sprogfield($field, $separator = '_') Feldname mit Sprach-Suffix (z.B. name_1)
sprogvalue($array, $field, $fallback_clang_id = 0) Wert aus Array mit Sprach-Suffix
sprogarray($array, $fields, $fallback_clang_id = 0) Mehrere Felder mit Suffix hinzufügen

Hinweise

⚠️ Platzhalter-Namen: Keine Leer- oder Sonderzeichen, nur a-z, 0-9, _, -

⚠️ Clang-Switch-Modus: Admin-Berechtigung erforderlich zum Ändern von Wildcard-Namen

⚠️ Sync-Funktionen: Vorsicht bei Aktivierung - automatische Änderungen über alle Sprachen!

⚠️ Sprachbasis: Gut bei wenigen Unterschieden, kann aber redundante Daten verschleiern

⚠️ Performance: Bei vielen Platzhaltern (> 500) kann Parsing langsam werden → Caching empfohlen


Verwandte Addons


GitHub: https://github.com/tbaddade/redaxo_sprog