Champ par champ
Titres et textes ont une valeur par langue. Prix, images, dates et références restent partagés : une nouvelle photo apparaît dans toutes les langues à la fois.
Traduction
Déclarez vos langues une fois. Chaque champ est traduisible ou partagé, les traductions vivent à côté de l’original, et vos rédacteurs, votre IA et vos agents traduisent dans le même éditeur. Pas une copie de chaque page par langue.

Titres et textes ont une valeur par langue. Prix, images, dates et références restent partagés : une nouvelle photo apparaît dans toutes les langues à la fois.
Une entrée contient toutes les langues. Ajouter une langue ne double jamais vos pages, vos menus ni vos relations.
Changez de langue dans la barre d’outils et modifiez la page traduite. Les champs vides affichent l’original en indication.
Traduire avec l’IA remplit ce qui manque avec votre contexte de marque, garde le HTML et les noms de produits, et attend votre relecture.
Claude, Codex ou Cursor lisent l’original, écrivent la traduction et listent ce qui reste, sans jamais remplacer un texte relu.
Ce qui n’est pas encore traduit, jusqu’à une ligne de liste, reprend l’original. Chaque langue a son état : manquante, partielle, à revoir, complète.
Les langues vivent dans leiho.schema.json avec le reste de votre modèle de contenu. La première est la langue par défaut : son contenu ne bouge pas.
{
"leiho": "collections",
"version": 1,
"i18n": { "default": "en", "locales": ["en", "fr", "de"] },
"collections": [
{ "id": "service", "path": "/services/{slug}", "fields": [
{ "name": "title", "type": "text" },
{ "name": "price", "type": "number", "localized": false }
] }
]
}Chargez l’export dans chaque langue. Les éléments traduits ont des chemins en /fr/ et l’adresse de chaque langue, prêts pour un sélecteur de langue et hreflang.
import { loadLeihoContent, indexLeihoContent } from 'leiho/content';
const fr = indexLeihoContent(
(await loadLeihoContent({ url: 'https://cms.example.com', locale: 'fr' })).data
);
const page = fr.byPath('/fr/services/audit');
page.translations; // { en: '/services/audit', fr: '/fr/services/audit' }Les traductions sont rangées dans une seule table, une ligne par entrée et par langue, à part de l’original. Dix langues, ce sont dix lignes, pas dix copies du site à synchroniser.
leiho/list-translations montre ce qui manque, leiho/get-translation donne l’original par chemin, leiho/update-translation l’écrit. Sur une entrée publiée, un agent ne peut remplir que les traductions vides.
Gratuit et open source. Essayez-le sur un vrai WordPress, dans votre navigateur.