Skip to content

Development.fr

Doug Blank edited this page Sep 22, 2026 · 1 revision

🌐 English · Deutsch

Développement

Cette page couvre la mise en place d'un environnement de développement local pour app/ lui-même — par opposition à Installation (exécuter la version pour ordinateur empaquetée) ou Déploiement (exécuter la forme de production conteneurisée). Voir d'abord Architecture pour comment les pièces s'assemblent.

Premiers pas

npm install                 # installe le workspace (app/ + packages/gramps-date)
cp app/.env.example app/.env.local   # pointe vers une instance gramps-web-api en cours d'exécution
npm run dev -w app          # démarre le serveur de développement Vite

app/ a besoin d'un véritable backend gramps-web-api à qui parler — c'est un client pur, il n'y a pas de mode données factices. L'option la plus légère est dev-fixtures/layer2-local-cache/api-fixture-example/setup.sh (voir Fixtures de développement ci-dessous).

Chaque fixture exécute gramps-web-api depuis un checkout des sources dans le même environnement Python que le script de fixture, cet environnement a donc besoin de :

pip install -e ~/gramps/gramps --no-deps          # gramps lui-même
pip install -e ~/gramps/gramps-web-api --no-deps  # + ses dépendances, voir ci-dessous
python3 deploy/webapi-requirements.py ~/gramps/gramps-web-api/pyproject.toml \
  | pip install -r /dev/stdin

Le const.py de gramps-web-api fait gi.require_version("Gtk", "3.0") à l'import, un vrai PyGObject et les typelibs GTK3 doivent donc être présents (apt install python3-gi gir1.2-gtk-3.0, ou conda install -c conda-forge pygobject gtk3) ; PyICU est optionnel mais fait taire un avertissement de localisation et corrige le tri des noms.

À noter : les endpoints /api/<type>/query/ sur lesquels app/ est construit ont atterri dans le master de gramps-project/gramps-web-api — un fork ou une branche plus ancienne renvoie un 404 pour chacun d'eux.

Fixtures de développement

dev-fixtures/ contient de véritables backends gramps-web-api pour faire tourner app/ localement contre eux. Ils ne font pas partie du produit livré — juste ce qui rend le développement local possible sans configurer un serveur à la main. Lire un script avant de l'exécuter — aucun d'eux n'est idempotent contre un arbre déjà peuplé. Chaque fixture se connecte comme gramps/gramps.

  • layer2-local-cache/api-fixture-example/ — l'option la plus légère : une instance en pur SQLite sur :5002 chargée avec la propre base de données d'exemple officielle de Gramps example.gramps, utile pour une vraie variété de dates (modificateurs, qualité, plages/intervalles). Définir VITE_API_BASE=http://localhost:5002 dans app/.env.local pour y pointer. La synchronisation en direct fonctionne aussi contre elle, puisque ce n'est qu'une requête contre /api/transactions/history/, pas lié à Postgres.
  • layer2-local-cache/api-fixture/ — une autre instance en pur SQLite, chargée avec des données synthétiques générées par gramps-bench à la place, pour des tests de mise à l'échelle contre un grand arbre.
  • layer3-sync/api-fixture/ — une instance adossée à un véritable Postgres (SharedPostgreSQL), utile pour exercer des modifications réellement concurrentes de plusieurs rédacteurs contre le même arbre. C'est ce que le VITE_API_BASE par défaut de app/.env.example vise, et cela nécessite un Postgres en cours d'exécution plus l'extension SharedPostgreSQL en plus de tout ce dont les fixtures SQLite ont besoin.

Construire les wheels de Gramplet

Les Gramplets exécutent du Python dans le navigateur sous Pyodide, contre des wheels construits localement que l'étape postinstall de npm install saute (avec une ligne de log) quand ils ne sont pas encore là — laissant les Gramplets échouer à l'exécution avec No known package with name 'gramps-gen-lib'. Les construire une fois :

python3 scripts/build-stub-wheels.py    # substituts gi + orjson pour Pyodide
python3 scripts/build-gramps-wheel.py   # gramps.gen.lib comme wheel Pyodide
node app/scripts/copy-wasm.mjs          # les enregistre dans public/pyodide/

Tester

npm run test -w app         # Vitest : logique pure de store/sync, pas de rendu complet de l'application
npm run typecheck -w app    # tsc --noEmit
npm run test -w packages/gramps-date
pytest tests/               # préréglages de filtre GOQL intégrés vs. vraies règles gramps-core

La suite pytest (tests/gql_presets/, voir son propre README) vérifie chaque préréglage de Filtres intégré (app/src/data/gqlFilterPresets.ts) contre la vraie classe Rule de gramps-core qu'il est censé porter, exécuté contre le propre arbre d'exemple fourni avec gramps-core — cela ne vérifie pas seulement « est-ce que ça compile » mais « est-ce que ça sélectionne les mêmes lignes que la règle de bureau ». Nécessite que gramps/gramps-object-query-language soit importable (déjà vrai partout où gramps-web-api lui-même tourne) ; aucune étape séparée n'est nécessaire pour garder sa propre instantanée JSON des préréglages synchronisée, cela se passe automatiquement.

Traductions

Les chaînes d'interface de app/ passent par t() (app/src/i18n/i18n.ts), ce qui reflète la propre approche de gramps-web — un simple lookup {anglais: traduit}, aucune bibliothèque i18n — fusionné à partir de deux sources par langue, choisi au moment de setLanguage() et mis en cache en mémoire jusqu'au prochain changement de langue :

  • Le vocabulaire de l'application de bureau Gramps — traduit en direct, par requête, en envoyant par POST les chaînes réellement utilisées à l'endpoint déjà existant GET/POST /api/translations/<lang> de gramps-web-api, qui les fait passer par le propre catalogue gettext du paquet gramps installé. Aucune copie statique à garder synchronisée ; toujours aussi fraîche que la version de gramps que le serveur a installée. La liste fixe des chaînes du vocabulaire de bureau à demander vit dans le tableau desktopStrings de i18n.ts — enrichie à la main, une entrée par chaîne, chaque fois qu'un appel t() nouvellement enveloppé s'avère être du vrai vocabulaire Gramps plutôt que quelque chose de spécifique à gramps-connect.
  • Les propres chaînes d'interface de gramps-web, et les chaînes des add-ons Gramps — amorcées comme fichiers statiques app/public/lang/{locale}.json (suivis dans git, l'application fonctionne donc sans que personne ait besoin d'une connexion Weblate) par scripts/bootstrap-translations.py, qui lit ../gramps-web/lang/ et ../addons-source/*/po/*-local.po — des checkouts frères de ce dépôt, pas un appel réseau. L'exécuter (python3 scripts/bootstrap-translations.py, nécessite pip install polib) chaque fois que ces checkouts frères sont mis à jour et que le corpus statique doit être rafraîchi ; il n'est câblé dans aucune étape de build, rien ne l'exécute donc automatiquement. Sûr à réexécuter : sans --force il saute tout .json de locale déjà existant, et même avec --force il n'écrase jamais que des fichiers sous app/public/lang/ — aucun appel réseau, aucune opération git, et tout mauvais résultat n'est qu'à un git checkout d'être annulé.

Envelopper davantage des propres chaînes de l'application dans t() est un travail continu et incrémental — app/scripts/wrap-translations.mjs est un codemod à usage unique (conservé comme outil réutilisable) qui enveloppe mécaniquement le texte JSX simple et une liste blanche d'attributs sûrs (label/title/placeholder) ; tout ce qui provient d'une variable ou d'une propriété d'objet littéral (configurations de vue/colonne dans app/src/store/views.ts, données d'API dynamiques, appels notifications.show()) nécessite à la place un t(...) manuel à l'endroit où le composant correspondant le rend.

Contribuer

Les discussions ont lieu sur le forum Discourse de Gramps ; les issues et pull requests contre le dépôt gramps-connect sont les bienvenues.

Licence

AGPL-3.0-or-later, assortie à gramps-web-api et gramps-web. packages/gramps-date traduit du code GPL-2.0-or-later du cœur de Gramps dans la base de code AGPL-3.0-or-later de ce projet — voir son propre README (et Architecture) pour comment ces deux licences se combinent.

Clone this wiki locally