Internationalisierung (i18n)
EmDash integriert sich in Astros eingebaute i18n-Routing, um mehrsprachige Inhaltsverwaltung bereitzustellen. Astro übernimmt URL-Routing und Lokalisierungserkennung; EmDash übernimmt die Speicherung und Abfrage übersetzter Inhalte.
Jede Übersetzung ist ein vollständiger, unabhängiger Inhalteintrag mit eigener URL (Slug), Status und Revisionshistorie. Die französische Version eines Beitrags kann sich im Entwurfsstatus befinden, während die englische Version veröffentlicht ist.
Konfiguration
Abschnitt betitelt „Konfiguration“Aktivieren Sie i18n, indem Sie einen i18n-Block zu Ihrer Astro-Konfiguration hinzufügen. EmDash liest diese Konfiguration automatisch – es ist keine separate Lokalisierungseinrichtung in EmDash erforderlich.
import { defineConfig } from "astro/config";import emdash, { local } from "emdash/astro";import { sqlite } from "emdash/db";
export default defineConfig({ i18n: { defaultLocale: "en", locales: ["en", "fr", "es"], fallback: { fr: "en", es: "en" }, }, integrations: [ emdash({ database: sqlite({ url: "file:./data.db" }), storage: local({ directory: "./uploads", baseUrl: "/_emdash/api/media/file", }), }), ],});Wenn i18n in der Astro-Konfiguration nicht vorhanden ist, sind alle i18n-Funktionen deaktiviert und EmDash verhält sich wie ein einsprachiges CMS.
Wie Übersetzungen funktionieren
Abschnitt betitelt „Wie Übersetzungen funktionieren“EmDash verwendet ein Zeile-pro-Lokalisierung-Modell. Jede Übersetzung ist eine eigene Zeile in der Datenbank mit eigener ID, eigenem Slug und eigenem Status, die über eine gemeinsame translation_group-Kennung mit anderen Übersetzungen verknüpft ist.
ec_posts:id | slug | locale | translation_group | status---------|-------------|--------|-------------------|----------01ABC... | my-post | en | 01ABC... | published01DEF... | mon-article | fr | 01ABC... | draft01GHI... | mi-entrada | es | 01ABC... | publishedDieses Design bedeutet:
- Lokalisierungsspezifische Slugs –
/blog/my-postund/fr/blog/mon-articlefunktionieren natürlich - Lokalisierungsspezifische Veröffentlichung – Veröffentlichen Sie die englische Version, während die französische im Entwurf bleibt
- Lokalisierungsspezifische Revisionen – jede Übersetzung hat ihre eigene Revisionshistorie
- Keine komplexen abfrageübergreifenden Lokalisierungen – Listenabfragen geben Einträge nur für eine Lokalisierung zurück
Abfragen übersetzter Inhalte
Abschnitt betitelt „Abfragen übersetzter Inhalte“Einzelner Eintrag
Abschnitt betitelt „Einzelner Eintrag“Übergeben Sie locale an getEmDashEntry, um eine bestimmte Übersetzung abzurufen. Wenn es weggelassen wird, wird standardmäßig die aktuelle Lokalisierung der Anfrage (gesetzt durch Astros i18n-Middleware) verwendet.
astro title="src/pages/[...slug].astro"---import { getEmDashEntry } from "emdash";
const { slug } = Astro.params;const { entry: post, error } = await getEmDashEntry("posts", slug, { locale: Astro.currentLocale,});
if (!post) return Astro.redirect("/404");---
<article> <h1>{post.data.title}</h1></article>Fallback-Kette
Abschnitt betitelt „Fallback-Kette“Wenn kein Inhalt für die angeforderte Lokalisierung existiert, folgt EmDash der in Ihrer Astro-Konfiguration definierten Fallback-Kette. Bei fallback: { fr: "en" }:
- Versuche die angeforderte Lokalisierung (
fr) - Versuche die Fallback-Lokalisierung (
en) - Versuche die Standardlokalisierung
Fallback gilt nur für Einzeleintragsabfragen. Listenabfragen geben Einträge nur für die angeforderte Lokalisierung zurück – keine abfrageübergreifende Vermischung.
Auflistung einer Sammlung
Abschnitt betitelt „Auflistung einer Sammlung“Filtern Sie eine Sammlung nach Lokalisierung:
astro title="src/pages/posts.astro"---import { getEmDashCollection } from "emdash";
const { entries: posts } = await getEmDashCollection("posts", { locale: Astro.currentLocale, status: "published",});---
<ul> {posts.map((post) => ( <li><a href={`/${post.data.slug}`}>{post.data.title}</a></li> ))}</ul>Sprachumschalter
Abschnitt betitelt „Sprachumschalter“Verwenden Sie getTranslations, um einen Sprachumschalter zu erstellen, der zu vorhandenen Übersetzungen des aktuellen Eintrags verlinkt:
astro title="src/components/LanguageSwitcher.astro"---import { getTranslations } from "emdash";import { getRelativeLocaleUrl } from "astro:i18n";
interface Props { collection: string; entryId: string;}
const { collection, entryId } = Astro.props;const { translations } = await getTranslations(collection, entryId);---
<nav aria-label="Language"> <ul> {translations.map((t) => ( <li> <a href={getRelativeLocaleUrl(t.locale, `/blog/${t.slug}`)} aria-current={t.locale === Astro.currentLocale ? "page" : undefined} > {t.locale.toUpperCase()} </a> </li> ))} </ul></nav>Die Funktion getTranslations gibt alle Lokalisierungsvarianten in derselben Übersetzungsgruppe zurück:
const { translationGroup, translations } = await getTranslations("posts", post.entry.id);// translations: [// { locale: "en", id: "01ABC...", slug: "my-post", status: "published" },// { locale: "fr", id: "01DEF...", slug: "mon-article", status: "draft" },// ]Übersetzungen im Admin verwalten
Abschnitt betitelt „Übersetzungen im Admin verwalten“Inhaltsliste
Abschnitt betitelt „Inhaltsliste“Wenn i18n aktiviert ist, zeigt die Inhaltsliste:
- Eine Lokalisierungsspalte, die die Lokalisierung jedes Eintrags anzeigt
- Einen Lokalisierungsfilter in der Werkzeugleiste, um zwischen Lokalisierungen zu wechseln
Übersetzungen erstellen
Abschnitt betitelt „Übersetzungen erstellen“Öffnen Sie einen beliebigen Inhalteintrag im Editor. Die Seitenleiste zeigt ein Übersetzungen-Panel an, das alle konfigurierten Lokalisierungen auflistet. Für jede Lokalisierung:
- “Übersetzen” erscheint für Lokalisierungen ohne Übersetzung – klicken Sie, um eine zu erstellen
- “Bearbeiten” erscheint für Lokalisierungen mit einer vorhandenen Übersetzung – klicken Sie, um zu dieser zu navigieren
- Die aktuelle Lokalisierung ist mit einem Häkchen markiert
Beim Erstellen einer Übersetzung wird der neue Eintrag mit Daten aus der Quelllokalisierung vorausgefüllt und erhält einen Standardslug von {source-slug}-{locale}. Passen Sie den Slug und den Inhalt nach Bedarf an und speichern Sie dann.
Lokalisierungsspezifische Veröffentlichung
Abschnitt betitelt „Lokalisierungsspezifische Veröffentlichung“Jede Übersetzung hat ihren eigenen Status. Veröffentlichen Sie, machen Sie unveröffentlicht oder planen Sie Übersetzungen unabhängig voneinander. Die französische Version kann sich im Entwurf befinden, während die englische Version live ist.
Inhalts-API
Abschnitt betitelt „Inhalts-API“Lokalisierungsparameter
Abschnitt betitelt „Lokalisierungsparameter“Alle Inhalts-API-Routen akzeptieren einen optionalen locale-Abfrageparameter:
GET /_emdash/api/content/posts?locale=frGET /_emdash/api/content/posts/my-post?locale=frWenn er weggelassen wird, wird standardmäßig die konfigurierte Standardlokalisierung verwendet.
Übersetzungen über die API erstellen
Abschnitt betitelt „Übersetzungen über die API erstellen“Erstellen Sie eine Übersetzung, indem Sie locale und translationOf an den Inhaltserstellungs-Endpunkt übergeben:
POST /_emdash/api/content/postsContent-Type: application/json
{ "locale": "fr", "translationOf": "01ABC...", "data": { "title": "Mon Article", "slug": "mon-article" }}Der neue Eintrag teilt sich die translation_group des Quelleintrags und startet als Entwurf.
Übersetzungen auflisten
Abschnitt betitelt „Übersetzungen auflisten“Rufen Sie alle Übersetzungen für einen bestimmten Eintrag ab:
GET /_emdash/api/content/posts/01ABC.../translationsGibt die Übersetzungsgruppen-ID und ein Array von Lokalisierungsvarianten mit ihren IDs, Slugs und Status zurück.
Die CLI unterstützt --locale-Flags bei Inhaltsbefehlen:
# List French postsemdash content list posts --locale fr
# Einen bestimmten Eintrag auf Französisch abrufenemdash content get posts my-post --locale fr
# Eine französische Übersetzung eines vorhandenen Eintrags erstellenemdash content create posts --locale fr --translation-of 01ABC...Mehrsprachige Inhalte vorab füllen (Seeding)
Abschnitt betitelt „Mehrsprachige Inhalte vorab füllen (Seeding)“Seed-Dateien drücken Übersetzungen mit locale und translationOf aus:
json title=".emdash/seed.json"{ "content": { "posts": [ { "id": "welcome", "slug": "welcome", "locale": "en", "status": "published", "data": { "title": "Welcome" } }, { "id": "welcome-fr", "slug": "bienvenue", "locale": "fr", "translationOf": "welcome", "status": "draft", "data": { "title": "Bienvenue" } } ] }}Der Quelllokalisierungseintrag muss vor seinen Übersetzungen in der Seed-Datei erscheinen, damit translationOf-Referenzen korrekt aufgelöst werden.
Übersetzbarkeit von Feldern
Abschnitt betitelt „Übersetzbarkeit von Feldern“Jedes Feld hat eine translatable-Einstellung (Standard: true). Beim Erstellen einer Übersetzung:
- Übersetzbare Felder werden aus der Quelllokalisierung zur Bearbeitung vorausgefüllt
- Nicht übersetzbare Felder werden kopiert und über alle Übersetzungen in der Gruppe synchron gehalten
Systemfelder wie status, published_at und author_id sind immer lokalisierungsspezifisch und werden nie synchronisiert.
URL-Strategie
Abschnitt betitelt „URL-Strategie“EmDash verwaltet keine Locale-URLs — Astro übernimmt das Routing. Gängige Muster:
# prefix-other-locales (Astro default)/blog/my-post → en (default locale, no prefix)/fr/blog/mon-article → fr
# prefix-always/en/blog/my-post → en/fr/blog/mon-article → frVerwenden Sie getRelativeLocaleUrl aus astro:i18n, um korrekte URLs unabhängig vom Routing-Modus zu erstellen.
Mehrsprachige Inhalte importieren
Abschnitt betitelt „Mehrsprachige Inhalte importieren“WordPress mit WPML oder Polylang
Abschnitt betitelt „WordPress mit WPML oder Polylang“Die WordPress-Plugin-Importquelle erkennt WPML und Polylang automatisch. Bei Erkennung enthalten importierte Inhalte Locale- und Übersetzungsgruppen-Metadaten, wodurch die mehrsprachige Struktur erhalten bleibt.
WXR-Dateien
Abschnitt betitelt „WXR-Dateien“WXR-Exporte enthalten keine WPML-/Polylang-Metadaten. Importieren Sie als einzelne Locale und erstellen Sie Übersetzungen manuell, oder verwenden Sie das Flag --locale, um allen importierten Elementen eine Locale zuzuweisen:
# Import a French WXR exportemdash import wordpress export-fr.xml --execute --locale fr
# An vorhandene englische Inhalte per Slug anpassenemdash import wordpress export-fr.xml --execute --locale fr --translation-of-locale enNächste Schritte
Abschnitt betitelt „Nächste Schritte“- Inhalte abfragen — Vollständige Query-API-Referenz
- Mit Inhalten arbeiten — Inhaltsverwaltung im Admin
- Astro i18n Routing — Astros Routing-Konfiguration