i18n Manager — Integrationsleitfaden

Integrationsleitfaden

Wie Sie den i18n Manager neben einem bestehenden Projekt platzieren und damit die Übersetzungen dieses Projekts verwalten — ohne den Technologie-Stack Ihrer Anwendung zu ändern.

Integrationsmodelle

Der i18n Manager ist ein eigenständiges Admin-Werkzeug mit eigener Datenbank. Der empfohlene Ansatz besteht darin, ihn als eigenständigen Dienst zu betreiben und Ihr Projekt seine Übersetzungen lesen zu lassen. Ihr Projekt importiert niemals den PHP-Code — es konsumiert nur Daten.

ModellWieAm besten geeignet für
A. Eigenständiger Dienst (empfohlen) Stellen Sie den Manager unter einem eigenen Host/vHost bereit (z. B. https://i18n.yourcompany.com) mit einer dedizierten Datenbank. Ihr Projekt liest über dessen API. Jeder Stack. Hält die Zuständigkeiten getrennt; keine Pfadkonflikte.
B. Datenquelle zur Build-Zeit Betreiben Sie den Manager lokal/intern, exportieren Sie JSON je Sprache und committen Sie diese Dateien in die bestehende i18n-Pipeline Ihres Projekts. Statische Websites, Bundler, Offline-Laufzeit, keine zusätzliche Netzwerkabhängigkeit in der Produktion.
Warum nicht in den Projektordner einbinden? Die Anwendung geht davon aus, dass sie an der Domain-Wurzel ausgeliefert wird (absolute /api/, /includes/, $_SERVER['DOCUMENT_ROOT']). Sie als eigene Anwendung zu betreiben vermeidet das Überarbeiten dieser Pfade — und ist der Weg, den diese Rezepte voraussetzen.

Der Abruf-Endpunkt

Alles, was Ihr Projekt benötigt, stammt aus einem einzigen Endpunkt:

GET {MANAGER}/api/translations_i18n.php

Query params (all optional):
  namespace=nav      # only keys in this namespace
  search=home        # ILIKE match on key/description
  format=json        # json (default) or js

Response (format=json) — a flat map of every active language:
{
  "nav.home":      { "en": "Home", "de": "Startseite" },
  "home.welcome":  { "en": "Welcome", "de": "Willkommen" }
}

Mit format=js werden dieselben Daten als var i18n = {…}; zurückgegeben (Content-Type application/javascript) — praktisch zum Laden über ein einfaches <script>-Tag. Für eine Datei mit einer einzelnen Sprache (z. B. zum Committen je Locale) verwenden Sie /api/translations_export.php?language=de&format=json.

Schlagen Sie einen String als map[key][lang] nach und greifen Sie auf eine Standardsprache zurück (üblicherweise en), wenn ein Schlüssel/eine Sprache fehlt.

Rezept — PHP-Projekt

Rufen Sie die Map einmal ab, cachen Sie sie in einer lokalen Datei und stellen Sie eine winzige t()-Hilfsfunktion bereit. Das hält die Produktion schnell und widerstandsfähig, falls der Manager kurzzeitig nicht erreichbar ist.

<?php
// i18n.php — In Ihr Projekt einfügen
const I18N_MANAGER  = 'https://i18n.yourcompany.com';
const I18N_CACHE    = __DIR__ . '/cache/i18n.json';
const I18N_TTL      = 300;            // Sekunden
const I18N_FALLBACK = 'en';

function i18n_map(): array {
    // Aus dem Cache bedienen, wenn er aktuell ist
    if (is_file(I18N_CACHE) && time() - filemtime(I18N_CACHE) < I18N_TTL) {
        return json_decode(file_get_contents(I18N_CACHE), true) ?: [];
    }
    // Vom Manager aktualisieren
    $url  = I18N_MANAGER . '/api/translations_i18n.php?format=json';
    $json = @file_get_contents($url);
    if ($json !== false) {
        @mkdir(dirname(I18N_CACHE), 0775, true);
        file_put_contents(I18N_CACHE, $json, LOCK_EX);
        return json_decode($json, true) ?: [];
    }
    // Auf den letzten guten Cache zurückfallen, selbst wenn er veraltet ist
    return is_file(I18N_CACHE)
        ? (json_decode(file_get_contents(I18N_CACHE), true) ?: [])
        : [];
}

function t(string $key, ?string $lang = null): string {
    static $map = null;
    $map  ??= i18n_map();
    $lang ??= $_SESSION['lang'] ?? I18N_FALLBACK;
    return $map[$key][$lang]
        ?? $map[$key][I18N_FALLBACK]
        ?? $key;                       // den Schlüssel anzeigen, wenn nichts gefunden wird
}
?>

<!-- Verwendung in einem Template -->
<h1><?= htmlspecialchars(t('home.welcome')) ?></h1>
HTML-Schlüssel: Werte, die im Manager als contains HTML markiert sind, enthalten Markup. Geben Sie diese mit echo t(...) aus (ohne Escaping); escapen Sie alles andere mit htmlspecialchars(), um XSS zu vermeiden.

Rezept — JavaScript / SPA

Die Lokalisierungs-Engine des Dashboards selbst ist vollständig wiederverwendbar. Speichern Sie diese als i18n.js, liefern Sie sie aus Ihrem Projekt aus und versehen Sie Elemente mit data-i18n, genau wie es der Manager tut.

// i18n.js — framework-freier Laufzeit-Lokalisierer
(function (global) {
  const MANAGER  = 'https://i18n.yourcompany.com';
  const FALLBACK = 'en';
  let map = {};

  async function load() {
    const res = await fetch(`${MANAGER}/api/translations_i18n.php?format=json`);
    map = await res.json();
    return map;
  }

  function t(key, lang) {
    const e = map[key];
    return (e && (e[lang] ?? e[FALLBACK])) ?? key;
  }

  function apply(lang) {
    localStorage.setItem('lang', lang);
    document.documentElement.setAttribute('lang', lang);
    document.querySelectorAll('[data-i18n]').forEach(el => {
      const v = t(el.getAttribute('data-i18n'), lang);
      if (v != null) el.textContent = v;
    });
    document.querySelectorAll('[data-i18n-html]').forEach(el => {
      const v = t(el.getAttribute('data-i18n-html'), lang);
      if (v != null) el.innerHTML = v;            // nur für vertrauenswürdige HTML-Schlüssel
    });
    document.querySelectorAll('[data-i18n-placeholder]').forEach(el => {
      const v = t(el.getAttribute('data-i18n-placeholder'), lang);
      if (v != null) el.setAttribute('placeholder', v);
    });
  }

  global.I18n = { load, t, apply };
})(window);

// bootstrap
I18n.load().then(() => I18n.apply(localStorage.getItem('lang') || 'en'));
<!-- Verwendung -->
<h1 data-i18n="home.welcome">Welcome</h1>
<input data-i18n-placeholder="filter.searchplaceholder" placeholder="Search…">
<script src="/i18n.js"></script>
CORS: Wenn sich Ihr Projekt und der Manager auf unterschiedlichen Origins befinden, muss der Manager für den Browser-Fetch Access-Control-Allow-Origin senden. Falls Sie das nicht aktivieren können, verwenden Sie stattdessen den Export zur Build-Zeit und liefern Sie eine JSON-Datei vom selben Origin aus.

Rezept — Export zur Build-Zeit

Für statische Websites oder Bundler erstellen Sie zur Build-Zeit einen Snapshot der Übersetzungen und liefern Sie diese mit Ihrer Anwendung aus — keine Laufzeitabhängigkeit vom Manager.

# Whole map (all languages) → commit as one file
curl -s "https://i18n.yourcompany.com/api/translations_i18n.php?format=json" \
     -o src/locales/i18n.json

# Or one file per language
for L in en de fr; do
  curl -s "https://i18n.yourcompany.com/api/translations_export.php?language=$L&format=json" \
       -o "src/locales/$L.json"
done

Binden Sie diesen curl-Schritt in Ihren prebuild/CI ein, damit jedes Release die neuesten Übersetzungen übernimmt.

Schlüssel aus Ihrem Projekt hinzufügen

Der mitgelieferte Scanner findet Übersetzungsschlüssel im Markup Ihres Projekts und erstellt das Gerüst für den Import in den Manager. Richten Sie ihn auf Ihr Projektstammverzeichnis:

# Discover keys in your project not yet in the manager's DB,
# and machine-translate them into every language.
node tools/scan_i18n_keys.js \
     --root /path/to/your/project \
     --endpoint https://i18n.yourcompany.com/api/translations_i18n.php \
     --translate \
     --out seeds

Dies schreibt seeds/new_keys.json (in den Tab Bulk Import des Managers einfügen) und seeds/new_keys.sql (gegen die DB ausführen). Übersetzer verfeinern und prüfen die Werte anschließend in der UI.

Caching & Cache-Invalidierung

Checkliste vor dem Produktivbetrieb

Einschränkungen, die zu beachten sind

Kurzreferenz

BedarfVerwenden
Alle Übersetzungen, alle Sprachen (Laufzeit)GET /api/translations_i18n.php?format=json
Dasselbe, als JS-VariableGET /api/translations_i18n.php?format=js
Eine Sprache, herunterladbare DateiGET /api/translations_export.php?language=de&format=json
Nur ein Namensraum…translations_i18n.php?namespace=nav
Neue Schlüssel in Ihrem Projekt entdeckennode tools/scan_i18n_keys.js --root … --endpoint …
Vollständige API-ReferenzSwagger · ReDoc