powersync-docs/README.md
Patrick Schurig 4c1b8a2be9 ci(optimiseur): récupération du moteur, génération et --check de la référence optimiseur
Nouvelle étape : clone --depth 1 de la branche par défaut du moteur
(même jeton, branche lue par l'API Gitea, comme pour les plugins) dans
.engine-src/ ; un échec de clone fait échouer le build, faute de quoi la
référence serait générée sans source. Génération avant mkdocs build,
--check avec les autres contrôles d'idempotence.

README : ligne du tableau des générateurs, commandes locales, pipeline,
et la règle de langue de ce bloc (cadre anglais, descriptions du
contrat en français, non traduites).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 13:09:42 +02:00

121 lines
6.5 KiB
Markdown

# powersync-docs
Documentation ETM PowerSync — [docs.etm-powersync.fr](https://docs.etm-powersync.fr)
MkDocs Material, **docs-as-code**, trois langues : `fr` (défaut) · `de` · `en`.
Licence : CC-BY-4.0 pour la documentation, GPL-3.0 pour les exemples de code.
---
## La règle qui explique tout le reste
**95 % du volume est GÉNÉRÉ, pas rédigé.** Mesure du 2026-10-12 : 74 013 mots générés
contre 3 506 mots de prose, sur 107 pages. Tout ce qui est entre
```
<!-- BEGIN GENERATED: <clé> --> … <!-- END GENERATED -->
```
est produit par un script depuis une source de vérité, et **écrasé à chaque passage**.
Éditer à l'intérieur de ces marqueurs, c'est écrire quelque chose qui disparaîtra.
| Générateur | Source de vérité | Produit |
|---|---|---|
| `scripts/gen_device_reference.py` | `PORTING_STATUS.yaml` + les `integrationplugin*.json` et `meta.json` des 5 dépôts de plugins | fiches appareils, index de catégorie, matrice de compatibilité, `appareils/SUMMARY.md` |
| `scripts/gen_api_reference.py` | `introspect.json` (introspection nymea) | référence JSON-RPC (23 pages), `api/SUMMARY.md` |
| `scripts/gen_optimizer_reference.py` | `docs/etm-powersync-optimizer-protocol.openrpc.json` du moteur (`etm-powersync-energy-plugin-etm`, branche par défaut) | tableaux de messages, listes fermées, règles nommées et machine de repli de `optimiseur/protocole*.md`, fiche de `optimiseur/contrat*.md`, copie servie du contrat ; garde-fou de contenu (IP privées, « cloud », « Héos ») |
## Multi-langue — où passe la frontière
Deux régimes, et ils ne se traitent pas pareil :
- **Le bloc de référence est en ANGLAIS, une seule fois, servi identique dans les trois
langues.** Décision du 2026-10-12. La raison est une mesure, pas un goût : nymea ne sert
**aucune** traduction sur notre parc — vérifié sur le banc `hems`, où
`Integrations.GetThingClasses` rend la **même charge utile au sha256 près** (243 340 octets)
pour `fr_FR`, `de_DE` et `en_US`. Les noms de modèles, de registres et d'unités sont donc
déjà en anglais ; traduire les seuls en-têtes de colonnes autour aurait fabriqué des pages
bilingues sans rien gagner. Le vocabulaire vit dans le dict `REF` de chaque générateur.
**Cas particulier, la référence optimiseur** (2026-10-18) : le cadre est en anglais
comme partout, mais les descriptions viennent du contrat du moteur, écrit en
français. Les traduire ici ferait une seconde vérité : elles sont reprises telles
quelles, et l'en-tête de colonne le dit (« from the contract, French »).
- **La prose et la navigation se TRADUISENT.** Fichiers suffixés (`page.md` = fr,
`page.de.md`, `page.en.md`), libellés de nav par `nav_translations` dans `mkdocs.yml`,
échafaudage des pages créées par le dict `SCAFFOLD` du générateur appareils.
> **Pourquoi `SCAFFOLD` existe.** Sans lui, chaque nouvel appareil ajouté créerait sa fiche
> dans la seule langue par défaut, et `fallback_to_default` la servirait **en français** sous
> `/de/` et `/en/`. Le générateur crée donc les trois variantes — et **ne réécrit jamais** une
> page existante, pour que la prose traduite à la main survive aux régénérations.
### Localisation ≠ traduction
`docs/tarifs.md` est l'exemple à connaître : la version FR parle de Tempo et du signal RTE,
la DE de `§14a EnWG` et de SMARD, l'EN des deux. Ce ne sont **pas** des traductions l'une de
l'autre, et c'est volontaire — les signaux tarifaires sont nationaux. Même traitement pour la
ligne correspondante de `docs/fonctionnalites/index.md`.
---
## Travailler dessus
```bash
python3 -m venv .venv && . .venv/bin/activate
pip install -r requirements.txt
# Prévisualiser (les trois langues sont construites ensemble)
mkdocs serve
# Régénérer la référence appareils — exige les JSON des 5 dépôts de plugins
# dans .plugins-src/ (la CI les clone ; en local, copiez-les depuis le workspace)
python3 scripts/gen_device_reference.py --src .plugins-src --docs docs \
--lang fr --locales fr,de,en
# Régénérer la référence API
python3 scripts/gen_api_reference.py --src introspect.json --docs docs
# Régénérer la référence du protocole optimiseur — exige le contrat OpenRPC du moteur
# (la CI clone le moteur dans .engine-src/ ; en local, --src accepte le clone,
# un dossier qui contient le fichier, ou le fichier lui-même)
python3 scripts/gen_optimizer_reference.py --src .engine-src/etm-powersync-energy-plugin-etm --docs docs
# Ce que vérifie la CI : rien ne doit changer après régénération
mkdocs build --strict
python3 scripts/gen_device_reference.py --src .plugins-src --docs docs \
--lang fr --locales fr,de,en --check
python3 scripts/gen_optimizer_reference.py --src .engine-src/etm-powersync-energy-plugin-etm \
--docs docs --check
```
### Le sélecteur de langue
Material affiche son icône `translate` — l'idéogramme 文 collé à un A. Elle dit
« traduire », pas « vous êtes en français », et à la taille du bandeau on y voit un
symbole asiatique plutôt qu'une langue. Depuis le 2026-10-15, `stylesheets/extra.css`
la masque et affiche à la place **le drapeau de la langue courante plus son code**,
comme sur etm-powersync.fr. La langue courante est aussi mise en évidence dans la
liste déroulante, où les trois lignes étaient jusque-là identiques.
Le drapeau se choisit sur `html[lang]`, que `mkdocs-static-i18n` pose déjà par locale.
**Aucun gabarit du thème n'est surchargé** — rien à reprendre à chaque mise à jour de
Material. Les drapeaux sont des SVG en `data:` (les emojis drapeaux ne se rendent pas
sous Windows) et le `aria-label` du bouton est inchangé : c'est lui qui porte le sens
pour les lecteurs d'écran, le code « FR » du `::after` restant décoratif.
⚠️ `mkdocs build --strict` **échoue sur un simple avertissement**. C'est pour cela que
`navigation.instant` est retiré de `theme.features` : il est incompatible avec le lien
contextuel du sélecteur de langue de `mkdocs-static-i18n`. Le commentaire est dans
`mkdocs.yml`, à l'endroit du retrait.
## Déploiement
CI Gitea (`.gitea/workflows/docs.yml`) sur push vers `main`, plus un passage nocturne à 3 h
(les `meta.json` des dépôts de plugins bougent sans que ce dépôt-ci bouge). Pipeline :
clone des 5 dépôts de plugins et du moteur → génération appareils → génération API →
génération optimiseur → `mkdocs build --strict` → contrôle d'idempotence → `rsync` vers
le serveur.
Le build produit `site/` (fr), `site/de/` et `site/en/` en une passe ; le `rsync --delete`
pousse l'ensemble.