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.
| Modell | Wie | Am 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. |
/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.
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>
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>
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
- Cachen Sie die Map in Ihrem Projekt (das PHP-Rezept zeigt einen TTL-basierten Datei-Cache). Der Manager sendet
Cache-Control: no-store, daher liegt das Caching in der Verantwortung Ihres Projekts. - Bei Veröffentlichung invalidieren — erhöhen Sie einen Versions-Query-Parameter (z. B.
?v=2025-06-18), wenn sich Übersetzungen ändern, oder verlassen Sie sich einfach auf die TTL. - Sanft scheitern — behalten Sie immer die letzte gute Kopie und fallen Sie auf sie zurück (sowie auf die Fallback-Sprache und schließlich auf den Schlüssel selbst), damit eine fehlende Übersetzung niemals eine Seite zerstört.
Checkliste vor dem Produktivbetrieb
- Authentifizierung — der Manager hat standardmäßig keine. Stellen Sie ihn hinter eine Authentifizierung (Reverse-Proxy-Basic-Auth, SSO, VPN oder IP-Allow-List), sodass nur Übersetzer schreiben können. Die Lese-Endpunkte können öffentlich bleiben, wenn Ihre Inhalte nicht sensibel sind.
- Externalisieren Sie DB-Zugangsdaten in
classes/class_pgsql_data.php(Umgebungsvariablen) und rotieren Sie jeden Wert, der committet wurde. - Dedizierte Datenbank für den Manager; Ihr Projekt liest über die API, nicht durch gemeinsame Nutzung von Tabellen.
- HTTPS auf dem Manager, damit abgerufene Übersetzungen während der Übertragung nicht manipuliert werden.
- CORS konfiguriert, falls Sie das Laufzeit-Modell (JS) über mehrere Origins hinweg verwenden.
Einschränkungen, die zu beachten sind
- Locale-Codes haben 2 Buchstaben (
en,de). Keine regionalen Varianten wieen-USoderpt-BRohne eine Schemaänderung. - Keine Pluralisierung oder Variableninterpolation — Werte sind einfache Strings/HTML. Wenn Sie
{count} itemsoder Pluralregeln benötigen, behandeln Sie das in Ihrer eigenen Rendering-Schicht auf Basis der zurückgegebenen Strings. - Der Namensraum ist nur der Text vor dem ersten Punkt.
- PostgreSQL liegt dem Manager unabhängig von der Datenbank Ihres Projekts zugrunde — Ihr Projekt liest lediglich JSON.
Kurzreferenz
| Bedarf | Verwenden |
|---|---|
| Alle Übersetzungen, alle Sprachen (Laufzeit) | GET /api/translations_i18n.php?format=json |
| Dasselbe, als JS-Variable | GET /api/translations_i18n.php?format=js |
| Eine Sprache, herunterladbare Datei | GET /api/translations_export.php?language=de&format=json |
| Nur ein Namensraum | …translations_i18n.php?namespace=nav |
| Neue Schlüssel in Ihrem Projekt entdecken | node tools/scan_i18n_keys.js --root … --endpoint … |
| Vollständige API-Referenz | Swagger · ReDoc |