Merge branch 'develop'
- fix todo for server without tk - split claude.md into rules - integrate rtk for optimisation agent IA - todo to add command for claude - todo i18n use english key - more space when print command into execute.py - todo integrate deploy local clone - script format
This commit is contained in:
commit
b1eeeb6053
22 changed files with 1387 additions and 785 deletions
14
.claude/rules/01-versions.md
Normal file
14
.claude/rules/01-versions.md
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
# Versions supportées
|
||||
|
||||
| Odoo | Python | Poetry | Statut |
|
||||
|-------|----------|--------|------------|
|
||||
| 18.0 | 3.12.10 | 2.1.3 | **Défaut** |
|
||||
| 17.0 | 3.10.18 | 1.8.3 | Actif |
|
||||
| 16.0 | 3.10.18 | 1.8.3 | Actif |
|
||||
| 15.0 | 3.8.20 | 1.8.3 | Déprécié |
|
||||
| 14.0 | 3.8.20 | 1.5.0 | Déprécié |
|
||||
| 13.0 | 3.7.17 | 1.5.0 | Déprécié |
|
||||
| 12.0 | 3.7.17 | 1.5.0 | Déprécié |
|
||||
|
||||
Configuration dans `conf/supported_version_erplibre.json`.
|
||||
Fichiers de version : `.odoo-version`, `.erplibre-version`, `.poetry-version`, `.python-odoo-version`.
|
||||
45
.claude/rules/02-project-structure.md
Normal file
45
.claude/rules/02-project-structure.md
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
# Structure du projet
|
||||
|
||||
```
|
||||
erplibre/
|
||||
├── Makefile # Orchestrateur principal (inclut conf/make.*.Makefile)
|
||||
├── run.sh / odoo_bin.sh # Lanceurs Odoo (venv + PYTHONPATH)
|
||||
├── env_var.sh # Variables d'environnement globales
|
||||
├── conf/ # Configuration : Makefiles modulaires, versions, manifests CSV
|
||||
│ ├── make.installation.Makefile
|
||||
│ ├── make.test.Makefile
|
||||
│ ├── make.database.Makefile
|
||||
│ ├── make.docker.Makefile
|
||||
│ ├── make.code_generator.Makefile
|
||||
│ ├── make.installation.poetry.Makefile
|
||||
│ └── supported_version_erplibre.json
|
||||
├── manifest/ # Manifests Google Repo (XML) par version Odoo
|
||||
│ └── git_manifest_odoo{12..18}.0.xml
|
||||
├── requirement/ # Dépendances par version
|
||||
│ ├── pyproject.odooXX.0_pythonY.Z.toml
|
||||
│ ├── poetry.odooXX.0_pythonY.Z.lock
|
||||
│ └── requirements.odooXX.0_pythonY.Z.txt
|
||||
├── script/ # Scripts utilitaires (32+ catégories)
|
||||
│ ├── todo/ # CLI interactif principal (todo.py)
|
||||
│ ├── database/ # Opérations DB (restore, migrate, image_db)
|
||||
│ ├── addons/ # Gestion des modules (install, update, uninstall)
|
||||
│ ├── code_generator/ # Génération de modules Odoo
|
||||
│ ├── version/ # Changement de version
|
||||
│ ├── git/ # Opérations Git et Google Repo
|
||||
│ ├── maintenance/ # Formatage (black, isort, prettier)
|
||||
│ ├── test/ # Tests parallèles + coverage
|
||||
│ ├── docker/ # Build/run Docker
|
||||
│ ├── poetry/ # Gestion Poetry
|
||||
│ ├── deployment/ # Déploiement production
|
||||
│ └── selenium/ # Tests web automatisés
|
||||
├── docker/ # Dockerfiles + docker-compose par version
|
||||
├── addons/ # Répertoire des addons (géré par Google Repo)
|
||||
│ ├── OCA_*/ # Modules OCA
|
||||
│ ├── ERPLibre_*/ # Modules ERPLibre
|
||||
│ ├── TechnoLibre_*/ # Code generator + templates
|
||||
│ └── MathBenTech_*/ # Modules spécialisés
|
||||
├── odoo{12..18}.0/ # Sources Odoo par version
|
||||
├── doc/ # Documentation (DEVELOPMENT, PRODUCTION, MIGRATION, etc.)
|
||||
├── test/ # Framework de test
|
||||
└── private/ # Fichiers privés (non versionné)
|
||||
```
|
||||
63
.claude/rules/03-commands.md
Normal file
63
.claude/rules/03-commands.md
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
# Commandes essentielles
|
||||
|
||||
## Changement de version Odoo
|
||||
```bash
|
||||
make switch_odoo_18 # Passer à Odoo 18
|
||||
make switch_odoo_17 # Passer à Odoo 17
|
||||
make switch_odoo_16 # Passer à Odoo 16 (défaut)
|
||||
make switch_odoo_15 # Passer à Odoo 15
|
||||
make switch_odoo_14 # Passer à Odoo 14
|
||||
make switch_odoo_13 # Passer à Odoo 13
|
||||
make switch_odoo_12 # Passer à Odoo 12
|
||||
make switch_odoo_16_update # Passer + mettre à jour les dépendances
|
||||
```
|
||||
|
||||
## Exécution
|
||||
```bash
|
||||
make run # Lancer Odoo (port 8069)
|
||||
make run_test # Lancer avec la DB "test"
|
||||
./run.sh -d ma_base # Lancer avec une DB spécifique
|
||||
./odoo_bin.sh [args] # Exécuter odoo-bin directement
|
||||
```
|
||||
|
||||
## Base de données
|
||||
```bash
|
||||
make db_create_db_test # Créer la DB "test"
|
||||
make db_clone_test_to_test2 # Cloner test -> test2
|
||||
./script/database/db_restore.py --database NOM --image IMAGE
|
||||
./script/addons/install_addons_dev.sh DB module1,module2
|
||||
./script/addons/update_addons_all.sh DB
|
||||
```
|
||||
|
||||
## Tests
|
||||
```bash
|
||||
make test # Tests de base + format
|
||||
make test_full_fast # Tests complets en parallèle
|
||||
make test_full_fast_coverage # Avec couverture de code
|
||||
```
|
||||
|
||||
## Formatage du code
|
||||
```bash
|
||||
make format # Fichiers à commiter uniquement
|
||||
make format_all # Tout formater (parallèle)
|
||||
```
|
||||
|
||||
## Docker
|
||||
```bash
|
||||
make docker_run_daemon # Lancer en production
|
||||
make docker_build_odoo_18 # Builder l'image Odoo 18
|
||||
```
|
||||
|
||||
## Google Repo (gestion multi-dépôts)
|
||||
```bash
|
||||
make repo_show_status # Statut de tous les dépôts addons
|
||||
make repo_configure_all # Configurer tous les dépôts
|
||||
make repo_do_stash # Stash tous les dépôts
|
||||
.venv.erplibre/bin/repo sync # Synchroniser les dépôts
|
||||
```
|
||||
|
||||
## Installation
|
||||
```bash
|
||||
make install_os # Dépendances système
|
||||
make install_odoo_18 # Installer Odoo 18 complet
|
||||
```
|
||||
24
.claude/rules/04-code-conventions.md
Normal file
24
.claude/rules/04-code-conventions.md
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
# Conventions de code
|
||||
|
||||
## Python
|
||||
- Formateur : **Black** (profil par défaut, ligne max 79 pour les modules Odoo)
|
||||
- Imports : **isort** avec profil `black`, longueur de ligne 79
|
||||
- Linting : **Flake8** avec bugbear, max-line-length 80, max-complexity 16
|
||||
- Ignorer : E203, E501, W503 (compatibilité Black)
|
||||
|
||||
## XML / JSON / YAML
|
||||
- Formateur : **Prettier** (via npm)
|
||||
- Indentation : 4 espaces (XML/CSS/JS), 2 espaces (JSON/YAML)
|
||||
|
||||
## Fichiers
|
||||
- Encodage : UTF-8
|
||||
- Fins de ligne : LF (Unix)
|
||||
- Indentation : 4 espaces (Python, XML, CSS, JS), 2 espaces (JSON, YAML, RST, MD)
|
||||
- Retour à la ligne final : oui
|
||||
- Espaces en fin de ligne : supprimés
|
||||
|
||||
## Git
|
||||
- Branches : `develop` (développement), `master` (production)
|
||||
- Pas de submodules Git — utilise **Google Repo** pour les addons
|
||||
- Manifests XML dans `manifest/` pour chaque version Odoo
|
||||
- Format de commit : `[TYPE] description` (ex: `[FIX]`, `[UPD]`, `[ADD]`, `[REM]`)
|
||||
22
.claude/rules/05-environments.md
Normal file
22
.claude/rules/05-environments.md
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
# Architecture des environnements virtuels
|
||||
|
||||
```
|
||||
.venv.erplibre/ # Venv ERPLibre (outils : repo, poetry, coverage)
|
||||
.venv.odoo18/ # Venv Odoo 18 (Python 3.12)
|
||||
.venv.odoo17/ # Venv Odoo 17 (Python 3.10)
|
||||
.venv.odoo16/ # Venv Odoo 16 (Python 3.10)
|
||||
.venv.odoo14/ # Venv Odoo 14 (Python 3.8)
|
||||
.venv.odoo12/ # Venv Odoo 12 (Python 3.7)
|
||||
```
|
||||
|
||||
Géré via **pyenv** pour les multiples versions de Python.
|
||||
|
||||
## Système de dépendances
|
||||
|
||||
Chaque version Odoo a son propre ensemble dans `requirement/` :
|
||||
- `pyproject.odooXX.0_pythonY.Z.toml` — Configuration Poetry
|
||||
- `poetry.odooXX.0_pythonY.Z.lock` — Lock file Poetry
|
||||
- `requirements.odooXX.0_pythonY.Z.txt` — Requirements pip (fallback)
|
||||
- `ignore_requirements.odooXX.0.txt` — Paquets à ignorer
|
||||
|
||||
Mise à jour : `./script/poetry/poetry_update.py`
|
||||
9
.claude/rules/06-code-generator.md
Normal file
9
.claude/rules/06-code-generator.md
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
# Code Generator
|
||||
|
||||
ERPLibre inclut un système de génération de modules Odoo :
|
||||
- `script/code_generator/new_project.py` — Créer un nouveau module
|
||||
- `script/code_generator/create_from_existing_module.py` — Cloner un module existant
|
||||
- `addons/TechnoLibre_odoo-code-generator/` — Moteur de génération
|
||||
- `addons/TechnoLibre_odoo-code-generator-template/` — Templates
|
||||
|
||||
Documentation : `doc/CODE_GENERATOR.md`
|
||||
55
.claude/rules/07-documentation.md
Normal file
55
.claude/rules/07-documentation.md
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
# Documentation multilingue
|
||||
|
||||
La documentation est bilingue (anglais/français) via **mmg** (Multilingual Markdown Generator).
|
||||
|
||||
## Fonctionnement
|
||||
- Les fichiers sources sont les `.base.md` (contiennent les deux langues)
|
||||
- `mmg` génère : `FICHIER.md` (anglais) et `FICHIER.fr.md` (français)
|
||||
- Marqueurs : `<!-- [en] -->`, `<!-- [fr] -->`, `<!-- [common] -->` (blocs de code partagés)
|
||||
|
||||
## Commandes
|
||||
```bash
|
||||
make doc_markdown # Regénérer toute la doc multilingue
|
||||
```
|
||||
|
||||
## Convention
|
||||
- **Ne jamais modifier directement** les fichiers `.md` ou `.fr.md` générés
|
||||
- Toujours modifier le fichier `.base.md` correspondant, puis exécuter `make doc_markdown`
|
||||
- Les blocs de code vont dans `<!-- [common] -->`, le texte dans `<!-- [en] -->` et `<!-- [fr] -->`
|
||||
- En-tête obligatoire dans chaque `.base.md` :
|
||||
```
|
||||
<!---------------------------->
|
||||
<!-- multilingual suffix: en, fr -->
|
||||
<!-- no suffix: en -->
|
||||
<!---------------------------->
|
||||
```
|
||||
|
||||
## Fichiers concernés (30 fichiers)
|
||||
- Racine : `README`, `CHANGELOG`, `TODO`
|
||||
- `doc/` : DEVELOPMENT, PRODUCTION, DISCOVER, RUN, MIGRATION, WINDOWS_INSTALLATION, FAQ, GIT_REPO, POETRY, RELEASE, UPDATE, CONTRIBUTION, HOWTO, TODO, CODE_GENERATOR
|
||||
- `docker/` : README
|
||||
- `script/*/` : database, deployment, fork_github_repo, nginx, restful, selenium (2), todo, odoo/migration
|
||||
- `.github/ISSUE_TEMPLATE/` : bug_report, feature_request
|
||||
|
||||
## Internationalisation du CLI TODO (i18n)
|
||||
|
||||
Le CLI interactif `script/todo/todo.py` supporte le français et l'anglais.
|
||||
|
||||
### Architecture
|
||||
- **`script/todo/todo_i18n.py`** — Module de traduction (dictionnaire `TRANSLATIONS`, fonctions `t()`, `get_lang()`, `set_lang()`)
|
||||
- Les chaînes traduisibles utilisent `t("clé")` au lieu de texte en dur
|
||||
- Les entrées de `todo.json` peuvent avoir un champ `prompt_description_key` résolu via `t()` (fallback sur `prompt_description`)
|
||||
|
||||
### Résolution de la langue (priorité)
|
||||
1. Variable d'environnement `EL_LANG` (définie dans `env_var.sh`, défaut `"fr"`)
|
||||
2. Défaut : `"fr"`
|
||||
|
||||
### Comportement
|
||||
- Première exécution : prompt bilingue demande à l'utilisateur de choisir sa langue
|
||||
- Le choix est persisté dans `env_var.sh`
|
||||
- Changement de langue possible via le menu Execute > Langue/Language
|
||||
|
||||
### Ajouter une traduction
|
||||
1. Ajouter la clé dans `TRANSLATIONS` de `todo_i18n.py` avec les valeurs `"fr"` et `"en"`
|
||||
2. Remplacer la chaîne en dur par `t("ma_clé")` dans `todo.py`
|
||||
3. Pour les entrées JSON : ajouter `"prompt_description_key": "ma_clé"` dans `todo.json`
|
||||
9
.claude/rules/08-deployment.md
Normal file
9
.claude/rules/08-deployment.md
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
# Déploiement
|
||||
|
||||
- **Docker** : `docker-compose.yml` (PostgreSQL 18 + PostGIS 3.6)
|
||||
- **Systemd** : `script/systemd/` pour les services
|
||||
- **Nginx** : `script/nginx/` pour le reverse proxy
|
||||
- **SSL** : Certbot pour les certificats
|
||||
- **DNS** : `script/deployment/update_dns_cloudflare.py`
|
||||
|
||||
Plateformes supportées : Ubuntu 20.04-25.04, Linux Mint 22.3, Debian 12, Arch Linux, macOS (pyenv), Windows (WSL/Docker).
|
||||
49
.claude/rules/09-workflow.md
Normal file
49
.claude/rules/09-workflow.md
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
# Workflow Orchestration
|
||||
|
||||
## 1. Plan Mode Default
|
||||
- Enter plan mode for ANY non-trivial task (3+ steps or architectural decisions)
|
||||
- If something goes sideways, STOP and re-plan immediately
|
||||
- Don't keep pushing.
|
||||
- Use plan mode for verification steps, not just building
|
||||
- Write detailed specs upfront to reduce ambiguity
|
||||
|
||||
## 2. Subagent Strategy
|
||||
- Use subagents liberally to keep the main context window clean.
|
||||
- Offload research, exploration, and parallel analysis to subagents
|
||||
- For complex problems, throw more compute at it via subagents
|
||||
- One task per subagent for focused execution
|
||||
|
||||
## 3. Self-Improvement Loop
|
||||
- Capture Lessons: Update AGENT.md with any change in approach the user has asked you to make.
|
||||
- Write rules for yourself that prevent the same mistake
|
||||
- Ruthlessly iterate on these lessons until the mistake rate drops.
|
||||
- Review lessons at session start for relevant project
|
||||
|
||||
## 4. Verification Before Done
|
||||
- Never mark a task complete without proving it works
|
||||
- Diff behavior between main and your changes when relevant
|
||||
- Ask yourself, "Would a staff engineer approve this?"
|
||||
- Run tests, check logs, and demonstrate correctness.
|
||||
|
||||
## 5. Demand Elegance (Balanced)
|
||||
- For non-trivial changes, pause and ask, "Is there a more elegant way?"
|
||||
- If a fix feels hacky: "Knowing everything I know now, implement the elegant solution"
|
||||
- Skip this for simple, obvious fixes
|
||||
- Don't over-engineer.
|
||||
- Challenge your own work before presenting it
|
||||
|
||||
## 6. Autonomous Bug Fixing
|
||||
- When given a bug report, just fix it. Don't ask for hand-holding
|
||||
- Point at logs, errors, and failing tests.
|
||||
- Then resolve them.
|
||||
- Zero context switching required from the user
|
||||
- Go fix failing CI tests without being told how
|
||||
|
||||
## Task Management
|
||||
|
||||
1. **Plan First**: Write a plan to `tasks/todo.md` with checkable items.
|
||||
2. **Verify Plan**: Check in before starting implementation.
|
||||
3. **Track Progress**: Mark items complete as you go.
|
||||
4. **Explain Changes**: High-level summary at each step.
|
||||
5. **Document Results**: Add review section to `tasks/todo.md`
|
||||
6. **Capture Lessons**: Update `tasks/lessons.md` after corrections
|
||||
316
CLAUDE.md
316
CLAUDE.md
|
|
@ -6,256 +6,6 @@ ERPLibre est un fork communautaire d'Odoo Community Edition (OCE) supportant les
|
|||
Version actuelle : **1.6.0** | Licence : **AGPL-3.0+**
|
||||
Version Odoo par défaut : **18.0** (support officiel ERPLibre 1.6.0)
|
||||
|
||||
## Versions supportées
|
||||
|
||||
| Odoo | Python | Poetry | Statut |
|
||||
|-------|----------|--------|------------|
|
||||
| 18.0 | 3.12.10 | 2.1.3 | **Défaut** |
|
||||
| 17.0 | 3.10.18 | 1.8.3 | Actif |
|
||||
| 16.0 | 3.10.18 | 1.8.3 | Actif |
|
||||
| 15.0 | 3.8.20 | 1.8.3 | Déprécié |
|
||||
| 14.0 | 3.8.20 | 1.5.0 | Déprécié |
|
||||
| 13.0 | 3.7.17 | 1.5.0 | Déprécié |
|
||||
| 12.0 | 3.7.17 | 1.5.0 | Déprécié |
|
||||
|
||||
Configuration dans `conf/supported_version_erplibre.json`.
|
||||
Fichiers de version : `.odoo-version`, `.erplibre-version`, `.poetry-version`, `.python-odoo-version`.
|
||||
|
||||
## Structure du projet
|
||||
|
||||
```
|
||||
erplibre/
|
||||
├── Makefile # Orchestrateur principal (inclut conf/make.*.Makefile)
|
||||
├── run.sh / odoo_bin.sh # Lanceurs Odoo (venv + PYTHONPATH)
|
||||
├── env_var.sh # Variables d'environnement globales
|
||||
├── conf/ # Configuration : Makefiles modulaires, versions, manifests CSV
|
||||
│ ├── make.installation.Makefile
|
||||
│ ├── make.test.Makefile
|
||||
│ ├── make.database.Makefile
|
||||
│ ├── make.docker.Makefile
|
||||
│ ├── make.code_generator.Makefile
|
||||
│ ├── make.installation.poetry.Makefile
|
||||
│ └── supported_version_erplibre.json
|
||||
├── manifest/ # Manifests Google Repo (XML) par version Odoo
|
||||
│ └── git_manifest_odoo{12..18}.0.xml
|
||||
├── requirement/ # Dépendances par version
|
||||
│ ├── pyproject.odooXX.0_pythonY.Z.toml
|
||||
│ ├── poetry.odooXX.0_pythonY.Z.lock
|
||||
│ └── requirements.odooXX.0_pythonY.Z.txt
|
||||
├── script/ # Scripts utilitaires (32+ catégories)
|
||||
│ ├── todo/ # CLI interactif principal (todo.py)
|
||||
│ ├── database/ # Opérations DB (restore, migrate, image_db)
|
||||
│ ├── addons/ # Gestion des modules (install, update, uninstall)
|
||||
│ ├── code_generator/ # Génération de modules Odoo
|
||||
│ ├── version/ # Changement de version
|
||||
│ ├── git/ # Opérations Git et Google Repo
|
||||
│ ├── maintenance/ # Formatage (black, isort, prettier)
|
||||
│ ├── test/ # Tests parallèles + coverage
|
||||
│ ├── docker/ # Build/run Docker
|
||||
│ ├── poetry/ # Gestion Poetry
|
||||
│ ├── deployment/ # Déploiement production
|
||||
│ └── selenium/ # Tests web automatisés
|
||||
├── docker/ # Dockerfiles + docker-compose par version
|
||||
├── addons/ # Répertoire des addons (géré par Google Repo)
|
||||
│ ├── OCA_*/ # Modules OCA
|
||||
│ ├── ERPLibre_*/ # Modules ERPLibre
|
||||
│ ├── TechnoLibre_*/ # Code generator + templates
|
||||
│ └── MathBenTech_*/ # Modules spécialisés
|
||||
├── odoo{12..18}.0/ # Sources Odoo par version
|
||||
├── doc/ # Documentation (DEVELOPMENT, PRODUCTION, MIGRATION, etc.)
|
||||
├── test/ # Framework de test
|
||||
└── private/ # Fichiers privés (non versionné)
|
||||
```
|
||||
|
||||
## Commandes essentielles
|
||||
|
||||
### Changement de version Odoo
|
||||
```bash
|
||||
make switch_odoo_18 # Passer à Odoo 18
|
||||
make switch_odoo_17 # Passer à Odoo 17
|
||||
make switch_odoo_16 # Passer à Odoo 16 (défaut)
|
||||
make switch_odoo_15 # Passer à Odoo 15
|
||||
make switch_odoo_14 # Passer à Odoo 14
|
||||
make switch_odoo_13 # Passer à Odoo 13
|
||||
make switch_odoo_12 # Passer à Odoo 12
|
||||
make switch_odoo_16_update # Passer + mettre à jour les dépendances
|
||||
```
|
||||
|
||||
### Exécution
|
||||
```bash
|
||||
make run # Lancer Odoo (port 8069)
|
||||
make run_test # Lancer avec la DB "test"
|
||||
./run.sh -d ma_base # Lancer avec une DB spécifique
|
||||
./odoo_bin.sh [args] # Exécuter odoo-bin directement
|
||||
```
|
||||
|
||||
### Base de données
|
||||
```bash
|
||||
make db_create_db_test # Créer la DB "test"
|
||||
make db_clone_test_to_test2 # Cloner test -> test2
|
||||
./script/database/db_restore.py --database NOM --image IMAGE
|
||||
./script/addons/install_addons_dev.sh DB module1,module2
|
||||
./script/addons/update_addons_all.sh DB
|
||||
```
|
||||
|
||||
### Tests
|
||||
```bash
|
||||
make test # Tests de base + format
|
||||
make test_full_fast # Tests complets en parallèle
|
||||
make test_full_fast_coverage # Avec couverture de code
|
||||
```
|
||||
|
||||
### Formatage du code
|
||||
```bash
|
||||
make format # Fichiers à commiter uniquement
|
||||
make format_all # Tout formater (parallèle)
|
||||
```
|
||||
|
||||
Outils : **Black** (Python, ligne max 79), **isort** (profil black, ligne max 79), **Prettier** (XML/JSON), **Flake8** (ligne max 80, complexité max 16).
|
||||
|
||||
### Docker
|
||||
```bash
|
||||
make docker_run_daemon # Lancer en production
|
||||
make docker_build_odoo_18 # Builder l'image Odoo 18
|
||||
```
|
||||
|
||||
### Google Repo (gestion multi-dépôts)
|
||||
```bash
|
||||
make repo_show_status # Statut de tous les dépôts addons
|
||||
make repo_configure_all # Configurer tous les dépôts
|
||||
make repo_do_stash # Stash tous les dépôts
|
||||
.venv.erplibre/bin/repo sync # Synchroniser les dépôts
|
||||
```
|
||||
|
||||
### Installation
|
||||
```bash
|
||||
make install_os # Dépendances système
|
||||
make install_odoo_18 # Installer Odoo 18 complet
|
||||
```
|
||||
|
||||
## Conventions de code
|
||||
|
||||
### Python
|
||||
- Formateur : **Black** (profil par défaut, ligne max 79 pour les modules Odoo)
|
||||
- Imports : **isort** avec profil `black`, longueur de ligne 79
|
||||
- Linting : **Flake8** avec bugbear, max-line-length 80, max-complexity 16
|
||||
- Ignorer : E203, E501, W503 (compatibilité Black)
|
||||
|
||||
### XML / JSON / YAML
|
||||
- Formateur : **Prettier** (via npm)
|
||||
- Indentation : 4 espaces (XML/CSS/JS), 2 espaces (JSON/YAML)
|
||||
|
||||
### Fichiers
|
||||
- Encodage : UTF-8
|
||||
- Fins de ligne : LF (Unix)
|
||||
- Indentation : 4 espaces (Python, XML, CSS, JS), 2 espaces (JSON, YAML, RST, MD)
|
||||
- Retour à la ligne final : oui
|
||||
- Espaces en fin de ligne : supprimés
|
||||
|
||||
### Git
|
||||
- Branches : `develop` (développement), `master` (production)
|
||||
- Pas de submodules Git — utilise **Google Repo** pour les addons
|
||||
- Manifests XML dans `manifest/` pour chaque version Odoo
|
||||
|
||||
## Architecture des environnements virtuels
|
||||
|
||||
```
|
||||
.venv.erplibre/ # Venv ERPLibre (outils : repo, poetry, coverage)
|
||||
.venv.odoo18/ # Venv Odoo 18 (Python 3.12)
|
||||
.venv.odoo17/ # Venv Odoo 17 (Python 3.10)
|
||||
.venv.odoo16/ # Venv Odoo 16 (Python 3.10)
|
||||
.venv.odoo14/ # Venv Odoo 14 (Python 3.8)
|
||||
.venv.odoo12/ # Venv Odoo 12 (Python 3.7)
|
||||
```
|
||||
|
||||
Géré via **pyenv** pour les multiples versions de Python.
|
||||
|
||||
## Système de dépendances
|
||||
|
||||
Chaque version Odoo a son propre ensemble dans `requirement/` :
|
||||
- `pyproject.odooXX.0_pythonY.Z.toml` — Configuration Poetry
|
||||
- `poetry.odooXX.0_pythonY.Z.lock` — Lock file Poetry
|
||||
- `requirements.odooXX.0_pythonY.Z.txt` — Requirements pip (fallback)
|
||||
- `ignore_requirements.odooXX.0.txt` — Paquets à ignorer
|
||||
|
||||
Mise à jour : `./script/poetry/poetry_update.py`
|
||||
|
||||
## Code Generator
|
||||
|
||||
ERPLibre inclut un système de génération de modules Odoo :
|
||||
- `script/code_generator/new_project.py` — Créer un nouveau module
|
||||
- `script/code_generator/create_from_existing_module.py` — Cloner un module existant
|
||||
- `addons/TechnoLibre_odoo-code-generator/` — Moteur de génération
|
||||
- `addons/TechnoLibre_odoo-code-generator-template/` — Templates
|
||||
|
||||
Documentation : `doc/CODE_GENERATOR.md`
|
||||
|
||||
## Documentation multilingue
|
||||
|
||||
La documentation est bilingue (anglais/français) via **mmg** (Multilingual Markdown Generator).
|
||||
|
||||
### Fonctionnement
|
||||
- Les fichiers sources sont les `.base.md` (contiennent les deux langues)
|
||||
- `mmg` génère : `FICHIER.md` (anglais) et `FICHIER.fr.md` (français)
|
||||
- Marqueurs : `<!-- [en] -->`, `<!-- [fr] -->`, `<!-- [common] -->` (blocs de code partagés)
|
||||
|
||||
### Commandes
|
||||
```bash
|
||||
make doc_markdown # Regénérer toute la doc multilingue
|
||||
```
|
||||
|
||||
### Convention
|
||||
- **Ne jamais modifier directement** les fichiers `.md` ou `.fr.md` générés
|
||||
- Toujours modifier le fichier `.base.md` correspondant, puis exécuter `make doc_markdown`
|
||||
- Les blocs de code vont dans `<!-- [common] -->`, le texte dans `<!-- [en] -->` et `<!-- [fr] -->`
|
||||
- En-tête obligatoire dans chaque `.base.md` :
|
||||
```
|
||||
<!---------------------------->
|
||||
<!-- multilingual suffix: en, fr -->
|
||||
<!-- no suffix: en -->
|
||||
<!---------------------------->
|
||||
```
|
||||
|
||||
### Fichiers concernés (30 fichiers)
|
||||
- Racine : `README`, `CHANGELOG`, `TODO`
|
||||
- `doc/` : DEVELOPMENT, PRODUCTION, DISCOVER, RUN, MIGRATION, WINDOWS_INSTALLATION, FAQ, GIT_REPO, POETRY, RELEASE, UPDATE, CONTRIBUTION, HOWTO, TODO, CODE_GENERATOR
|
||||
- `docker/` : README
|
||||
- `script/*/` : database, deployment, fork_github_repo, nginx, restful, selenium (2), todo, odoo/migration
|
||||
- `.github/ISSUE_TEMPLATE/` : bug_report, feature_request
|
||||
|
||||
## Internationalisation du CLI TODO (i18n)
|
||||
|
||||
Le CLI interactif `script/todo/todo.py` supporte le français et l'anglais.
|
||||
|
||||
### Architecture
|
||||
- **`script/todo/todo_i18n.py`** — Module de traduction (dictionnaire `TRANSLATIONS`, fonctions `t()`, `get_lang()`, `set_lang()`)
|
||||
- Les chaînes traduisibles utilisent `t("clé")` au lieu de texte en dur
|
||||
- Les entrées de `todo.json` peuvent avoir un champ `prompt_description_key` résolu via `t()` (fallback sur `prompt_description`)
|
||||
|
||||
### Résolution de la langue (priorité)
|
||||
1. Variable d'environnement `EL_LANG` (définie dans `env_var.sh`, défaut `"fr"`)
|
||||
2. Défaut : `"fr"`
|
||||
|
||||
### Comportement
|
||||
- Première exécution : prompt bilingue demande à l'utilisateur de choisir sa langue
|
||||
- Le choix est persisté dans `env_var.sh`
|
||||
- Changement de langue possible via le menu Execute > Langue/Language
|
||||
|
||||
### Ajouter une traduction
|
||||
1. Ajouter la clé dans `TRANSLATIONS` de `todo_i18n.py` avec les valeurs `"fr"` et `"en"`
|
||||
2. Remplacer la chaîne en dur par `t("ma_clé")` dans `todo.py`
|
||||
3. Pour les entrées JSON : ajouter `"prompt_description_key": "ma_clé"` dans `todo.json`
|
||||
|
||||
## Déploiement
|
||||
|
||||
- **Docker** : `docker-compose.yml` (PostgreSQL 18 + PostGIS 3.6)
|
||||
- **Systemd** : `script/systemd/` pour les services
|
||||
- **Nginx** : `script/nginx/` pour le reverse proxy
|
||||
- **SSL** : Certbot pour les certificats
|
||||
- **DNS** : `script/deployment/update_dns_cloudflare.py`
|
||||
|
||||
Plateformes supportées : Ubuntu 20.04-25.04, Linux Mint 22.3, Debian 12, Arch Linux, macOS (pyenv), Windows (WSL/Docker).
|
||||
|
||||
## Points d'attention pour Claude
|
||||
|
||||
- Toujours vérifier la version Odoo active avant de modifier du code (`cat .odoo-version`)
|
||||
|
|
@ -270,58 +20,24 @@ Plateformes supportées : Ubuntu 20.04-25.04, Linux Mint 22.3, Debian 12, Arch L
|
|||
- Pour la documentation : modifier les `.base.md`, jamais les `.md` ou `.fr.md` directement
|
||||
- Outil mmg disponible via `source .venv.erplibre/bin/activate && mmg`
|
||||
|
||||
## Workflow Orchestration
|
||||
|
||||
### 1. Plan Mode Default
|
||||
- Enter plan mode for ANY non-trivial task (3+ steps or architectural decisions)
|
||||
- If something goes sideways, STOP and re-plan immediately
|
||||
- Don't keep pushing.
|
||||
- Use plan mode for verification steps, not just building
|
||||
- Write detailed specs upfront to reduce ambiguity
|
||||
|
||||
### 2. Subagent Strategy
|
||||
- Use subagents liberally to keep the main context window clean.
|
||||
- Offload research, exploration, and parallel analysis to subagents
|
||||
- For complex problems, throw more compute at it via subagents
|
||||
- One task per subagent for focused execution
|
||||
|
||||
### 3. Self-Improvement Loop
|
||||
- Capture Lessons: Update AGENT.md with any change in approach the user has asked you to make.
|
||||
- Write rules for yourself that prevent the same mistake
|
||||
- Ruthlessly iterate on these lessons until the mistake rate drops.
|
||||
- Review lessons at session start for relevant project
|
||||
|
||||
### 4. Verification Before Done
|
||||
- Never mark a task complete without proving it works
|
||||
- Diff behavior between main and your changes when relevant
|
||||
- Ask yourself, "Would a staff engineer approve this?"
|
||||
- Run tests, check logs, and demonstrate correctness.
|
||||
|
||||
### 5. Demand Elegance (Balanced)
|
||||
- For non-trivial changes, pause and ask, "Is there a more elegant way?"
|
||||
- If a fix feels hacky: "Knowing everything I know now, implement the elegant solution"
|
||||
- Skip this for simple, obvious fixes
|
||||
- Don't over-engineer.
|
||||
- Challenge your own work before presenting it
|
||||
|
||||
### 6. Autonomous Bug Fixing
|
||||
- When given a bug report, just fix it. Don't ask for hand-holding
|
||||
- Point at logs, errors, and failing tests.
|
||||
- Then resolve them.
|
||||
- Zero context switching required from the user
|
||||
- Go fix failing CI tests without being told how
|
||||
|
||||
## Task Management
|
||||
|
||||
1. **Plan First**: Write a plan to `tasks/todo.md` with checkable items.
|
||||
2. **Verify Plan**: Check in before starting implementation.
|
||||
3. **Track Progress**: Mark items complete as you go.
|
||||
4. **Explain Changes**: High-level summary at each step.
|
||||
5. **Document Results**: Add review section to `tasks/todo.md`
|
||||
6. **Capture Lessons**: Update `tasks/lessons.md` after corrections
|
||||
|
||||
## Core Principles
|
||||
|
||||
- **Simplicity First**: Make every change as simple as possible. Impact minimal code.
|
||||
- **No Laziness**: Find root causes. No temporary fixes. Senior developer standards.
|
||||
- **Minimal Impact**: Changes should only touch what's necessary. Avoid introducing bugs.
|
||||
|
||||
## Règles détaillées
|
||||
|
||||
Les instructions détaillées sont dans `.claude/rules/` :
|
||||
|
||||
| Fichier | Contenu |
|
||||
|---------|---------|
|
||||
| `01-versions.md` | Versions Odoo/Python/Poetry supportées |
|
||||
| `02-project-structure.md` | Arborescence du projet |
|
||||
| `03-commands.md` | Commandes essentielles (make, scripts) |
|
||||
| `04-code-conventions.md` | Conventions Python, XML, fichiers, Git |
|
||||
| `05-environments.md` | Venvs, pyenv, système de dépendances |
|
||||
| `06-code-generator.md` | Génération de modules Odoo |
|
||||
| `07-documentation.md` | Documentation multilingue (mmg) + i18n CLI |
|
||||
| `08-deployment.md` | Docker, systemd, nginx, SSL, DNS |
|
||||
| `09-workflow.md` | Workflow orchestration + task management |
|
||||
|
|
|
|||
143
conf/template_claude_commands_todo_add_command.md
Normal file
143
conf/template_claude_commands_todo_add_command.md
Normal file
|
|
@ -0,0 +1,143 @@
|
|||
---
|
||||
name: todo_add_command
|
||||
description: "Add a new menu command to script/todo/todo.py with i18n support and optional todo.json entry."
|
||||
allowed-tools:
|
||||
- Read
|
||||
- Edit
|
||||
- Write
|
||||
- Grep
|
||||
- Glob
|
||||
- Bash(python3 -m py_compile:*)
|
||||
- Bash(python3 -c:*)
|
||||
---
|
||||
|
||||
## Context
|
||||
|
||||
- Current todo.py menu structure: !`grep -n "def prompt_execute" script/todo/todo.py | head -20`
|
||||
- Current todo.json sections: !`python3 -c "import json; d=json.load(open('script/todo/todo.json')); print('\n'.join(d.keys()))"`
|
||||
- Current i18n keys count: !`grep -c fr.: script/todo/todo_i18n.py`
|
||||
|
||||
## Architecture Reference
|
||||
|
||||
### Files to modify
|
||||
|
||||
| File | Role |
|
||||
|------|------|
|
||||
| `script/todo/todo.py` | Main CLI — menu methods, business logic |
|
||||
| `script/todo/todo_i18n.py` | Translations dict `TRANSLATIONS` with `"fr"` and `"en"` keys |
|
||||
| `script/todo/todo.json` | Config-driven entries (optional, for `bash_command` or `makefile_cmd`) |
|
||||
|
||||
### Pattern A — Hardcoded menu entry (interactive logic)
|
||||
|
||||
Used when the command needs Python logic (user prompts, conditionals, API calls).
|
||||
|
||||
1. **Add i18n keys** in `todo_i18n.py` `TRANSLATIONS` dict:
|
||||
```python
|
||||
"my_feature_description": {
|
||||
"fr": "Description en français",
|
||||
"en": "English description",
|
||||
},
|
||||
```
|
||||
|
||||
2. **Add choice** in the parent menu method (e.g. `prompt_execute_git`):
|
||||
```python
|
||||
choices = [
|
||||
...,
|
||||
{"prompt_description": t("my_feature_description")},
|
||||
]
|
||||
```
|
||||
|
||||
3. **Add elif branch** in the same menu's while loop:
|
||||
```python
|
||||
elif status == "N":
|
||||
self._my_feature()
|
||||
```
|
||||
|
||||
4. **Add method** to the `TODO` class:
|
||||
```python
|
||||
def _my_feature(self):
|
||||
# Implementation here
|
||||
pass
|
||||
```
|
||||
|
||||
### Pattern B — Config-driven entry (simple bash command)
|
||||
|
||||
Used when the command just runs a bash command or a make target.
|
||||
|
||||
1. **Add i18n key** in `todo_i18n.py` (use `prompt_description_key`).
|
||||
|
||||
2. **Add entry** in `todo.json` under the appropriate `*_from_makefile` section:
|
||||
```json
|
||||
{
|
||||
"prompt_description_key": "my_i18n_key",
|
||||
"bash_command": "my-command --flag"
|
||||
}
|
||||
```
|
||||
Or for make targets:
|
||||
```json
|
||||
{
|
||||
"prompt_description_key": "my_i18n_key",
|
||||
"makefile_cmd": "my_make_target"
|
||||
}
|
||||
```
|
||||
|
||||
These are automatically picked up by `execute_from_configuration()`.
|
||||
|
||||
### Available menu sections
|
||||
|
||||
| Menu | Method | JSON key |
|
||||
|------|--------|----------|
|
||||
| Automation | `prompt_execute_function` | `function` |
|
||||
| Code | `prompt_execute_code` | `code_from_makefile` |
|
||||
| Config | `prompt_execute_config` | — |
|
||||
| Database | `prompt_execute_database` | — |
|
||||
| Doc | `prompt_execute_doc` | — |
|
||||
| Git | `prompt_execute_git` | `git_from_makefile` |
|
||||
| GPT code | `prompt_execute_gpt_code` | — |
|
||||
| Network | `prompt_execute_network` | — |
|
||||
| Process | `prompt_execute_process` | — |
|
||||
| Run | `prompt_execute_instance` | `instance` |
|
||||
| Security | `prompt_execute_security` | — |
|
||||
| Test | `prompt_execute_test` | — |
|
||||
| Update | `prompt_execute_update` | `update_from_makefile` |
|
||||
|
||||
### Key conventions
|
||||
|
||||
- i18n keys: `snake_case`, grouped by section with a comment header
|
||||
- Method names: `_private_method` for actions, `prompt_execute_*` for submenus
|
||||
- All user-facing strings must use `t("key")` — never hardcoded text
|
||||
- Use `self.execute.exec_command_live(cmd, source_erplibre=False)` to run bash
|
||||
- Use `input(t("prompt_key")).strip()` for user input
|
||||
- Use `click.prompt(help_info)` for menu navigation
|
||||
- Menu methods return `False` on back, use `self.fill_help_info(choices)` for formatting
|
||||
|
||||
## Task
|
||||
|
||||
Add a new command to the todo.py menu system. The user will describe what they want.
|
||||
|
||||
### Steps
|
||||
|
||||
1. **Determine the target menu section** from the user's description
|
||||
2. **Choose Pattern A or B** based on complexity:
|
||||
- Simple bash/make command → Pattern B (todo.json entry)
|
||||
- Needs user interaction or logic → Pattern A (hardcoded method)
|
||||
3. **Add i18n translations** in `todo_i18n.py` — always both `"fr"` and `"en"`
|
||||
4. **Implement the feature** following the appropriate pattern
|
||||
5. **Validate syntax**:
|
||||
```bash
|
||||
python3 -m py_compile script/todo/todo.py
|
||||
python3 -m py_compile script/todo/todo_i18n.py
|
||||
python3 -c "import json; json.load(open('script/todo/todo.json'))"
|
||||
```
|
||||
|
||||
### Rules
|
||||
|
||||
- Keep menu numbering sequential — update all `elif` branches if inserting
|
||||
- Group i18n keys with a `# Section name` comment
|
||||
- Match existing code style (Black, 79 char lines for Odoo modules)
|
||||
- Do not break existing menu entries or their numbering
|
||||
- Test that `fill_help_info` and `execute_from_configuration` handle the new entry
|
||||
|
||||
## User Request
|
||||
|
||||
$ARGUMENTS
|
||||
|
|
@ -96,9 +96,7 @@ def commit_by_directory():
|
|||
run_git_command(f'cd "{config.path}" && git rm -r {directory}')
|
||||
|
||||
# Crée le commit
|
||||
commit_message = (
|
||||
f"[{mig_prefix_msg}] {directory}: Migration to {config.odoo_version}"
|
||||
)
|
||||
commit_message = f"[{mig_prefix_msg}] {directory}: Migration to {config.odoo_version}"
|
||||
commit_result = run_git_command(
|
||||
f'cd "{config.path}" && git commit -m "{commit_message}"'
|
||||
)
|
||||
|
|
|
|||
|
|
@ -10,28 +10,31 @@ def get_db_list_xmlrpc(odoo_url):
|
|||
Retrieves the list of Odoo databases using the XML-RPC API.
|
||||
"""
|
||||
try:
|
||||
common = xmlrpc.client.ServerProxy(f'{odoo_url}/xmlrpc/db')
|
||||
common = xmlrpc.client.ServerProxy(f"{odoo_url}/xmlrpc/db")
|
||||
db_list = common.list()
|
||||
return db_list
|
||||
except xmlrpc.client.Fault as e:
|
||||
print(f"XML-RPC Error: {e.faultCode} - {e.faultString}", file=sys.stderr)
|
||||
print(
|
||||
f"XML-RPC Error: {e.faultCode} - {e.faultString}", file=sys.stderr
|
||||
)
|
||||
return []
|
||||
except Exception as e:
|
||||
print(f"Connection Error: {e}", file=sys.stderr)
|
||||
return []
|
||||
|
||||
|
||||
# --- CLI using Click ---
|
||||
@click.command()
|
||||
@click.option(
|
||||
'--odoo-url',
|
||||
default='http://localhost:8069',
|
||||
help='URL of the Odoo server.',
|
||||
show_default=True
|
||||
"--odoo-url",
|
||||
default="http://localhost:8069",
|
||||
help="URL of the Odoo server.",
|
||||
show_default=True,
|
||||
)
|
||||
@click.option(
|
||||
'--raw',
|
||||
"--raw",
|
||||
is_flag=True,
|
||||
help='Output one database per line, without extra formatting. Useful for scripting.'
|
||||
help="Output one database per line, without extra formatting. Useful for scripting.",
|
||||
)
|
||||
def list_databases(odoo_url, raw=False):
|
||||
"""
|
||||
|
|
@ -56,5 +59,5 @@ def list_databases(odoo_url, raw=False):
|
|||
|
||||
|
||||
# --- Script Execution ---
|
||||
if __name__ == '__main__':
|
||||
if __name__ == "__main__":
|
||||
list_databases()
|
||||
|
|
|
|||
|
|
@ -115,7 +115,7 @@ class Execute:
|
|||
command = self.cmd_source_default % command
|
||||
|
||||
if not quiet:
|
||||
print("🏠 ⬇ Execute command :")
|
||||
print("🏠 ⬇ Execute command :\n")
|
||||
print(command)
|
||||
output_lines = []
|
||||
|
||||
|
|
@ -172,10 +172,10 @@ class Execute:
|
|||
duration_delta = datetime.timedelta(seconds=duration_sec)
|
||||
human_time = humanize.precisedelta(duration_delta)
|
||||
if not quiet:
|
||||
print(f"🏠 ⬆ Executed ({human_time}) :")
|
||||
print(f"🏠 ⬆ Executed ({human_time}) :\n")
|
||||
else:
|
||||
if not quiet:
|
||||
print(f"🏠 ⬆ Executed ({duration_sec:.2f} sec.) :")
|
||||
print(f"🏠 ⬆ Executed ({duration_sec:.2f} sec.) :\n")
|
||||
if not quiet:
|
||||
print(command)
|
||||
print()
|
||||
|
|
|
|||
|
|
@ -151,8 +151,7 @@ Use --production-ready for /srv/git (requires root).
|
|||
type=int,
|
||||
default=DEFAULT_JOBS,
|
||||
help=(
|
||||
"Parallel jobs for init/remote/push"
|
||||
f" (default: {DEFAULT_JOBS})"
|
||||
"Parallel jobs for init/remote/push" f" (default: {DEFAULT_JOBS})"
|
||||
),
|
||||
)
|
||||
parser.add_argument(
|
||||
|
|
@ -247,11 +246,7 @@ def get_erplibre_root_project(erplibre_root):
|
|||
capture_output=True,
|
||||
text=True,
|
||||
)
|
||||
revision = (
|
||||
result.stdout.strip()
|
||||
if result.returncode == 0
|
||||
else "master"
|
||||
)
|
||||
revision = result.stdout.strip() if result.returncode == 0 else "master"
|
||||
|
||||
return {
|
||||
"name": ERPLIBRE_REPO_NAME,
|
||||
|
|
@ -278,19 +273,13 @@ async def _init_single_bare_repo(git_path, project, semaphore):
|
|||
return "skipped"
|
||||
|
||||
_logger.info(f" Creating: {bare_path}")
|
||||
_, err, rc = await _run_git(
|
||||
"git", "init", "--bare", bare_path
|
||||
)
|
||||
_, err, rc = await _run_git("git", "init", "--bare", bare_path)
|
||||
if rc != 0:
|
||||
_logger.warning(
|
||||
f" Init failed: {bare_path}: {err.strip()}"
|
||||
)
|
||||
_logger.warning(f" Init failed: {bare_path}: {err.strip()}")
|
||||
return "error"
|
||||
|
||||
# Enable git daemon export
|
||||
export_file = os.path.join(
|
||||
bare_path, "git-daemon-export-ok"
|
||||
)
|
||||
export_file = os.path.join(bare_path, "git-daemon-export-ok")
|
||||
open(export_file, "w").close()
|
||||
|
||||
# Allow pushing from shallow clones
|
||||
|
|
@ -312,10 +301,7 @@ async def init_bare_repos(git_path, projects, jobs):
|
|||
semaphore = asyncio.Semaphore(jobs)
|
||||
|
||||
results = await asyncio.gather(
|
||||
*[
|
||||
_init_single_bare_repo(git_path, p, semaphore)
|
||||
for p in projects
|
||||
]
|
||||
*[_init_single_bare_repo(git_path, p, semaphore) for p in projects]
|
||||
)
|
||||
|
||||
created = results.count("created")
|
||||
|
|
@ -352,9 +338,7 @@ async def _add_single_remote(
|
|||
):
|
||||
"""Add or update remote for a single repo (async)."""
|
||||
async with semaphore:
|
||||
repo_path = os.path.join(
|
||||
erplibre_root, project["path"]
|
||||
)
|
||||
repo_path = os.path.join(erplibre_root, project["path"])
|
||||
if not os.path.isdir(repo_path):
|
||||
_logger.warning(f" Not found: {repo_path}")
|
||||
return "error"
|
||||
|
|
@ -368,9 +352,7 @@ async def _add_single_remote(
|
|||
)
|
||||
|
||||
# Check if remote already exists
|
||||
stdout, _, _ = await _run_git(
|
||||
"git", "-C", repo_path, "remote"
|
||||
)
|
||||
stdout, _, _ = await _run_git("git", "-C", repo_path, "remote")
|
||||
existing_remotes = stdout.strip().split("\n")
|
||||
|
||||
if remote_name in existing_remotes:
|
||||
|
|
@ -403,8 +385,7 @@ async def _add_single_remote(
|
|||
)
|
||||
if rc != 0:
|
||||
_logger.warning(
|
||||
f" add failed for"
|
||||
f" {project['path']}: {err.strip()}"
|
||||
f" add failed for" f" {project['path']}: {err.strip()}"
|
||||
)
|
||||
return "error"
|
||||
_logger.info(f" Added: {project['path']}")
|
||||
|
|
@ -447,10 +428,7 @@ async def add_remotes(
|
|||
added = results.count("added")
|
||||
updated = results.count("updated")
|
||||
errors = results.count("error")
|
||||
print(
|
||||
f"Remotes: {added} added, {updated} updated,"
|
||||
f" {errors} errors"
|
||||
)
|
||||
print(f"Remotes: {added} added, {updated} updated," f" {errors} errors")
|
||||
|
||||
|
||||
# --- Async workers for push ---
|
||||
|
|
@ -458,9 +436,7 @@ async def add_remotes(
|
|||
|
||||
async def _is_detached_head(repo_path):
|
||||
"""Check if a repo is in detached HEAD state."""
|
||||
_, _, rc = await _run_git(
|
||||
"git", "-C", repo_path, "symbolic-ref", "HEAD"
|
||||
)
|
||||
_, _, rc = await _run_git("git", "-C", repo_path, "symbolic-ref", "HEAD")
|
||||
return rc != 0
|
||||
|
||||
|
||||
|
|
@ -471,9 +447,7 @@ async def _checkout_manifest_branch(repo_path, revision):
|
|||
on the exact commit. We create/checkout a local branch
|
||||
matching the manifest revision so git push works.
|
||||
"""
|
||||
branch = (
|
||||
revision.split("/")[-1] if "/" in revision else revision
|
||||
)
|
||||
branch = revision.split("/")[-1] if "/" in revision else revision
|
||||
|
||||
# Check if local branch already exists
|
||||
_, _, rc = await _run_git(
|
||||
|
|
@ -485,9 +459,7 @@ async def _checkout_manifest_branch(repo_path, revision):
|
|||
f"refs/heads/{branch}",
|
||||
)
|
||||
if rc == 0:
|
||||
await _run_git(
|
||||
"git", "-C", repo_path, "checkout", branch
|
||||
)
|
||||
await _run_git("git", "-C", repo_path, "checkout", branch)
|
||||
else:
|
||||
await _run_git(
|
||||
"git",
|
||||
|
|
@ -514,9 +486,7 @@ async def _update_bare_head(git_path, project):
|
|||
revision = project.get("revision", "")
|
||||
if not revision:
|
||||
return
|
||||
branch = (
|
||||
revision.split("/")[-1] if "/" in revision else revision
|
||||
)
|
||||
branch = revision.split("/")[-1] if "/" in revision else revision
|
||||
await _run_git(
|
||||
"git",
|
||||
"-C",
|
||||
|
|
@ -529,20 +499,10 @@ async def _update_bare_head(git_path, project):
|
|||
|
||||
async def _try_unshallow(repo_path, project, remote_name):
|
||||
"""Try to unshallow a repo by fetching full history."""
|
||||
shallow_file = os.path.join(
|
||||
repo_path, ".git", "shallow"
|
||||
)
|
||||
_logger.info(
|
||||
f" Unshallowing {project['path']}..."
|
||||
)
|
||||
stdout, _, _ = await _run_git(
|
||||
"git", "-C", repo_path, "remote"
|
||||
)
|
||||
remotes = [
|
||||
r
|
||||
for r in stdout.strip().split("\n")
|
||||
if r and r != remote_name
|
||||
]
|
||||
shallow_file = os.path.join(repo_path, ".git", "shallow")
|
||||
_logger.info(f" Unshallowing {project['path']}...")
|
||||
stdout, _, _ = await _run_git("git", "-C", repo_path, "remote")
|
||||
remotes = [r for r in stdout.strip().split("\n") if r and r != remote_name]
|
||||
manifest_remote = project.get("remote", "")
|
||||
if manifest_remote in remotes:
|
||||
remotes.remove(manifest_remote)
|
||||
|
|
@ -562,9 +522,7 @@ async def _try_unshallow(repo_path, project, remote_name):
|
|||
except asyncio.TimeoutError:
|
||||
continue
|
||||
if not os.path.exists(shallow_file):
|
||||
_logger.info(
|
||||
f" Unshallowed via {try_remote}"
|
||||
)
|
||||
_logger.info(f" Unshallowed via {try_remote}")
|
||||
return
|
||||
if os.path.exists(shallow_file):
|
||||
_logger.warning(
|
||||
|
|
@ -585,30 +543,22 @@ async def _push_single_repo(
|
|||
):
|
||||
"""Push a single repo to local remote (async)."""
|
||||
async with semaphore:
|
||||
repo_path = os.path.join(
|
||||
erplibre_root, project["path"]
|
||||
)
|
||||
repo_path = os.path.join(erplibre_root, project["path"])
|
||||
if not os.path.isdir(repo_path):
|
||||
_logger.warning(f" Not found: {repo_path}")
|
||||
return "error", False
|
||||
|
||||
# Handle shallow repos
|
||||
shallow_file = os.path.join(
|
||||
repo_path, ".git", "shallow"
|
||||
)
|
||||
shallow_file = os.path.join(repo_path, ".git", "shallow")
|
||||
if os.path.exists(shallow_file):
|
||||
if unshallow:
|
||||
await _try_unshallow(
|
||||
repo_path, project, remote_name
|
||||
)
|
||||
await _try_unshallow(repo_path, project, remote_name)
|
||||
else:
|
||||
# Enable shallow push on bare repo
|
||||
repo_name = project["name"]
|
||||
if not repo_name.endswith(".git"):
|
||||
repo_name += ".git"
|
||||
bare_path = os.path.join(
|
||||
git_path, repo_name
|
||||
)
|
||||
bare_path = os.path.join(git_path, repo_name)
|
||||
if os.path.isdir(bare_path):
|
||||
await _run_git(
|
||||
"git",
|
||||
|
|
@ -618,19 +568,14 @@ async def _push_single_repo(
|
|||
"receive.shallowUpdate",
|
||||
"true",
|
||||
)
|
||||
_logger.info(
|
||||
f" Shallow push for"
|
||||
f" {project['path']}"
|
||||
)
|
||||
_logger.info(f" Shallow push for" f" {project['path']}")
|
||||
|
||||
# Handle detached HEAD: checkout manifest branch
|
||||
did_checkout = False
|
||||
if await _is_detached_head(repo_path):
|
||||
revision = project.get("revision", "")
|
||||
if revision:
|
||||
branch = await _checkout_manifest_branch(
|
||||
repo_path, revision
|
||||
)
|
||||
branch = await _checkout_manifest_branch(repo_path, revision)
|
||||
_logger.info(
|
||||
f" Checkout {branch} for"
|
||||
f" {project['path']}"
|
||||
|
|
@ -663,9 +608,7 @@ async def _push_single_repo(
|
|||
"push",
|
||||
remote_name,
|
||||
]
|
||||
_, err, rc = await _run_git(
|
||||
*cmd, timeout=120
|
||||
)
|
||||
_, err, rc = await _run_git(*cmd, timeout=120)
|
||||
if rc != 0:
|
||||
_logger.warning(
|
||||
f" Push failed for"
|
||||
|
|
@ -675,14 +618,10 @@ async def _push_single_repo(
|
|||
return "error", did_checkout
|
||||
else:
|
||||
await _update_bare_head(git_path, project)
|
||||
_logger.info(
|
||||
f" Pushed: {project['path']}"
|
||||
)
|
||||
_logger.info(f" Pushed: {project['path']}")
|
||||
return "pushed", did_checkout
|
||||
except asyncio.TimeoutError:
|
||||
_logger.warning(
|
||||
f" Timeout pushing {project['path']}"
|
||||
)
|
||||
_logger.warning(f" Timeout pushing {project['path']}")
|
||||
return "error", did_checkout
|
||||
|
||||
|
||||
|
|
@ -744,8 +683,7 @@ def print_clone_commands(git_path, projects, port):
|
|||
if clone_path == ".":
|
||||
clone_path = "erplibre"
|
||||
lines.append(
|
||||
f" git clone {base_url}/{repo_name}"
|
||||
f" {clone_path}"
|
||||
f" git clone {base_url}/{repo_name}" f" {clone_path}"
|
||||
)
|
||||
lines.sort()
|
||||
for line in lines:
|
||||
|
|
|
|||
|
|
@ -26,17 +26,10 @@ def get_pull_request_repo(
|
|||
parsed_url = parse(upstream_url)
|
||||
|
||||
status, user = gh.user.get()
|
||||
user_name = (
|
||||
user["login"] if not organization_name else organization_name
|
||||
)
|
||||
status, lst_pull = (
|
||||
gh.repos[user_name][parsed_url.repo].pulls.get()
|
||||
)
|
||||
user_name = user["login"] if not organization_name else organization_name
|
||||
status, lst_pull = gh.repos[user_name][parsed_url.repo].pulls.get()
|
||||
if type(lst_pull) is dict:
|
||||
print(
|
||||
f"For url {upstream_url},"
|
||||
f" got {lst_pull.get('message')}"
|
||||
)
|
||||
print(f"For url {upstream_url}," f" got {lst_pull.get('message')}")
|
||||
return False
|
||||
else:
|
||||
for pull in lst_pull:
|
||||
|
|
@ -53,26 +46,21 @@ def fork_repo(
|
|||
parsed_url = parse(upstream_url)
|
||||
|
||||
status, user = gh.user.get()
|
||||
user_name = (
|
||||
user["login"] if not organization_name else organization_name
|
||||
)
|
||||
status, forked_repo = (
|
||||
gh.repos[user_name][parsed_url.repo].get()
|
||||
)
|
||||
user_name = user["login"] if not organization_name else organization_name
|
||||
status, forked_repo = gh.repos[user_name][parsed_url.repo].get()
|
||||
if status == 404:
|
||||
status, upstream_repo = (
|
||||
gh.repos[parsed_url.owner][parsed_url.repo].get()
|
||||
)
|
||||
status, upstream_repo = gh.repos[parsed_url.owner][
|
||||
parsed_url.repo
|
||||
].get()
|
||||
if status == 404:
|
||||
print("Unable to find repo %s" % upstream_url)
|
||||
exit(1)
|
||||
args = {}
|
||||
if organization_name:
|
||||
args["organization"] = organization_name
|
||||
status, forked_repo = (
|
||||
gh.repos[parsed_url.owner][parsed_url.repo]
|
||||
.forks.post(**args)
|
||||
)
|
||||
status, forked_repo = gh.repos[parsed_url.owner][
|
||||
parsed_url.repo
|
||||
].forks.post(**args)
|
||||
if status == 404:
|
||||
print(
|
||||
f"{Fore.RED}Error{Style.RESET_ALL} when forking"
|
||||
|
|
@ -82,23 +70,16 @@ def fork_repo(
|
|||
else:
|
||||
try:
|
||||
print(
|
||||
"Forked %s to %s"
|
||||
% (upstream_url, forked_repo["html_url"])
|
||||
"Forked %s to %s" % (upstream_url, forked_repo["html_url"])
|
||||
)
|
||||
except Exception as e:
|
||||
print(e)
|
||||
print(forked_repo)
|
||||
print(upstream_url)
|
||||
elif status == 202:
|
||||
print(
|
||||
"Forked repo %s already exists"
|
||||
% forked_repo["full_name"]
|
||||
)
|
||||
print("Forked repo %s already exists" % forked_repo["full_name"])
|
||||
elif status != 200:
|
||||
print(
|
||||
"Status not supported: %s - %s"
|
||||
% (status, forked_repo)
|
||||
)
|
||||
print("Status not supported: %s - %s" % (status, forked_repo))
|
||||
exit(1)
|
||||
|
||||
|
||||
|
|
@ -110,9 +91,7 @@ def add_and_fetch_remote(
|
|||
"""
|
||||
try:
|
||||
working_repo = Repo(repo_info.relative_path)
|
||||
if repo_info.organization in [
|
||||
a.name for a in working_repo.remotes
|
||||
]:
|
||||
if repo_info.organization in [a.name for a in working_repo.remotes]:
|
||||
print(
|
||||
f'Remote "{repo_info.organization}" already exist'
|
||||
f" in {repo_info.relative_path}"
|
||||
|
|
@ -122,8 +101,7 @@ def add_and_fetch_remote(
|
|||
print(f"New repo {repo_info.relative_path}")
|
||||
if not root_repo:
|
||||
print(
|
||||
"Missing git repository to root for repo"
|
||||
f" {repo_info.path}"
|
||||
"Missing git repository to root for repo" f" {repo_info.path}"
|
||||
)
|
||||
return
|
||||
if branch_name:
|
||||
|
|
@ -149,16 +127,14 @@ def add_and_fetch_remote(
|
|||
# Add remote
|
||||
upstream_remote = retry(
|
||||
wait_exponential_multiplier=1000, stop_max_delay=15000
|
||||
)(working_repo.create_remote)(
|
||||
repo_info.organization, repo_info.url_https
|
||||
)
|
||||
)(working_repo.create_remote)(repo_info.organization, repo_info.url_https)
|
||||
print(
|
||||
'Remote "%s" created for %s'
|
||||
% (repo_info.organization, repo_info.url_https)
|
||||
)
|
||||
|
||||
# Fetch the remote
|
||||
retry(
|
||||
wait_exponential_multiplier=1000, stop_max_delay=15000
|
||||
)(upstream_remote.fetch)()
|
||||
retry(wait_exponential_multiplier=1000, stop_max_delay=15000)(
|
||||
upstream_remote.fetch
|
||||
)()
|
||||
print('Remote "%s" fetched' % repo_info.organization)
|
||||
|
|
|
|||
|
|
@ -26,7 +26,9 @@ _logger = logging.getLogger(__name__)
|
|||
|
||||
PROJECT_NAME = os.path.basename(os.getcwd())
|
||||
IDEA_PATH = "./.idea"
|
||||
DEFAULT_ODOO_BIN = "./odoo/odoo-bin" # Need this to replace static configuration
|
||||
DEFAULT_ODOO_BIN = (
|
||||
"./odoo/odoo-bin" # Need this to replace static configuration
|
||||
)
|
||||
IDEA_MISC = os.path.join(IDEA_PATH, "misc.xml")
|
||||
IDEA_WORKSPACE = os.path.join(IDEA_PATH, "workspace.xml")
|
||||
VCS_WORKSPACE = os.path.join(IDEA_PATH, "vcs.xml")
|
||||
|
|
|
|||
|
|
@ -2,7 +2,9 @@
|
|||
# © 2021-2026 TechnoLibre (http://www.technolibre.ca)
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
|
||||
|
||||
installed_modules = env["ir.module.module"].search([('state', '=', 'installed')])
|
||||
installed_modules = env["ir.module.module"].search(
|
||||
[("state", "=", "installed")]
|
||||
)
|
||||
|
||||
print("Installed modules:")
|
||||
|
||||
|
|
|
|||
|
|
@ -10,18 +10,20 @@ print("Running a script in the Odoo shell!")
|
|||
# ERROR: insert or update on table "discuss_channel_member" violates foreign key constraint "discuss_channel_member_channel_id_fkey"
|
||||
# DÉTAIL : Key (channel_id)=(3) is not present in table "discuss_channel".
|
||||
|
||||
env.cr.execute("""
|
||||
env.cr.execute(
|
||||
"""
|
||||
ALTER TABLE discuss_channel
|
||||
DROP CONSTRAINT discuss_channel_channel_type_not_null;
|
||||
""")
|
||||
"""
|
||||
)
|
||||
env.cr.commit()
|
||||
|
||||
#env.cr.execute("SELECT to_regclass('public.discuss_channel');")
|
||||
#print("table:", env.cr.fetchone())
|
||||
# env.cr.execute("SELECT to_regclass('public.discuss_channel');")
|
||||
# print("table:", env.cr.fetchone())
|
||||
|
||||
#print(
|
||||
# print(
|
||||
# "model discuss.channel:",
|
||||
# env["ir.model"].search([("model", "=", "discuss.channel")]),
|
||||
#)
|
||||
# )
|
||||
|
||||
print("End fix migration with update mail postgresql 17 to postgresql 18.")
|
||||
|
|
|
|||
|
|
@ -10,47 +10,52 @@
|
|||
},
|
||||
"instance": [
|
||||
{
|
||||
"prompt_description_key": "json_instance_test",
|
||||
"prompt_description_key": "Test - Minimal base instance",
|
||||
"makefile_cmd": "db_restore_erplibre_base_db_test",
|
||||
"database": "test"
|
||||
},
|
||||
{
|
||||
"prompt_description_key": "json_robot_minimal",
|
||||
"prompt_description_key": "Open RobotLibre 🤖 minimal",
|
||||
"makefile_cmd": "robot_libre",
|
||||
"database": "robotlibre"
|
||||
},
|
||||
{
|
||||
"prompt_description_key": "json_robot_search",
|
||||
"prompt_description_key": "Open RobotLibre 🤖 with search enabled",
|
||||
"makefile_cmd": "robot_libre_all",
|
||||
"database": "robotlibre"
|
||||
}
|
||||
],
|
||||
"function": [
|
||||
{
|
||||
"prompt_description_key": "json_open_erplibre_todo",
|
||||
"prompt_description_key": "Open ERPLibre with TODO 🤖",
|
||||
"command": "./.venv.erplibre/bin/python ./script/selenium/web_login.py"
|
||||
}
|
||||
],
|
||||
"update_from_makefile": [
|
||||
{
|
||||
"prompt_description_key": "json_update_erplibre_base_test",
|
||||
"prompt_description_key": "Update all erplibre_base on database test",
|
||||
"makefile_cmd": "db_erplibre_base_db_test_update_all",
|
||||
"database": "test"
|
||||
}
|
||||
],
|
||||
"code_from_makefile": [
|
||||
{
|
||||
"prompt_description_key": "json_show_code_status",
|
||||
"prompt_description_key": "Show code status",
|
||||
"makefile_cmd": "repo_show_status"
|
||||
},
|
||||
{
|
||||
"prompt_description_key": "json_stash_all_code",
|
||||
"prompt_description_key": "Stash all code",
|
||||
"makefile_cmd": "repo_do_stash"
|
||||
},
|
||||
{
|
||||
"prompt_description_key": "json_format_modified_code",
|
||||
"prompt_description_key": "Format modified code",
|
||||
"makefile_cmd": "format"
|
||||
}
|
||||
],
|
||||
"git_from_makefile": []
|
||||
"git_from_makefile": [
|
||||
{
|
||||
"prompt_description_key": "Configure git local editor to vim",
|
||||
"bash_command": "git config --global core.editor \"vim\""
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -15,539 +15,732 @@ TRANSLATIONS = {
|
|||
"fr": "L'importation est un succès!",
|
||||
"en": "Importation success!",
|
||||
},
|
||||
"opening": {
|
||||
"Opening TODO ...": {
|
||||
"fr": "Ouverture de TODO en cours ...",
|
||||
"en": "Opening TODO ...",
|
||||
},
|
||||
"enter_directives": {
|
||||
"=> Enter your choice by number and press Enter!": {
|
||||
"fr": "=> Entre tes directives par son chiffre et fait Entrée!",
|
||||
"en": "=> Enter your choice by number and press Enter!",
|
||||
},
|
||||
"command": {
|
||||
"Command:": {
|
||||
"fr": "Commande :",
|
||||
"en": "Command:",
|
||||
},
|
||||
"menu_execute": {
|
||||
"Execute": {
|
||||
"fr": "Exécution",
|
||||
"en": "Execute",
|
||||
},
|
||||
"menu_install": {
|
||||
"Install": {
|
||||
"fr": "Installation",
|
||||
"en": "Install",
|
||||
},
|
||||
"menu_question": {
|
||||
"Question": {
|
||||
"fr": "Question",
|
||||
"en": "Question",
|
||||
},
|
||||
"menu_fork": {
|
||||
"Fork - Open TODO in a new tab": {
|
||||
"fr": "Fork - Ouvre TODO dans une nouvelle tabulation",
|
||||
"en": "Fork - Open TODO in a new tab",
|
||||
},
|
||||
"menu_quit": {
|
||||
"Quit": {
|
||||
"fr": "Quitter",
|
||||
"en": "Quit",
|
||||
},
|
||||
"cmd_not_found": {
|
||||
"Command not found !": {
|
||||
"fr": "Commande non trouvée !",
|
||||
"en": "Command not found !",
|
||||
},
|
||||
"back": {
|
||||
"Back": {
|
||||
"fr": "Retour",
|
||||
"en": "Back",
|
||||
},
|
||||
# Execute submenu
|
||||
"menu_run": {
|
||||
"Run - Execute and install an instance": {
|
||||
"fr": "Run - Exécuter et installer une instance",
|
||||
"en": "Run - Execute and install an instance",
|
||||
},
|
||||
"menu_automation": {
|
||||
"Automation - Demonstration of developed features": {
|
||||
"fr": "Automatisation - Demonstration des fonctions développées",
|
||||
"en": "Automation - Demonstration of developed features",
|
||||
},
|
||||
"menu_update": {
|
||||
"Update - Update all developed staging source code": {
|
||||
"fr": "Mise à jour - Update all developed staging source code",
|
||||
"en": "Update - Update all developed staging source code",
|
||||
},
|
||||
"menu_code": {
|
||||
"Code - Developer tools": {
|
||||
"fr": "Code - Outil pour développeur",
|
||||
"en": "Code - Developer tools",
|
||||
},
|
||||
"menu_doc": {
|
||||
"Doc - Documentation search": {
|
||||
"fr": "Doc - Recherche de documentation",
|
||||
"en": "Doc - Documentation search",
|
||||
},
|
||||
"menu_database": {
|
||||
"Database - Database tools": {
|
||||
"fr": "Database - Outils sur les bases de données",
|
||||
"en": "Database - Database tools",
|
||||
},
|
||||
"menu_process": {
|
||||
"Process - Execution tools": {
|
||||
"fr": "Process - Outils sur les executions",
|
||||
"en": "Process - Execution tools",
|
||||
},
|
||||
"menu_config": {
|
||||
"Config - Configuration file management": {
|
||||
"fr": "Config - Traitement du fichier de configuration",
|
||||
"en": "Config - Configuration file management",
|
||||
},
|
||||
"menu_network": {
|
||||
"Network - Network tools": {
|
||||
"fr": "Réseau - Outil réseautique",
|
||||
"en": "Network - Network tools",
|
||||
},
|
||||
"menu_security": {
|
||||
"Security - Dependency security audit": {
|
||||
"fr": "Sécurité - Audit de sécurité des dépendances",
|
||||
"en": "Security - Dependency security audit",
|
||||
},
|
||||
"menu_lang": {
|
||||
"RTK - CLI proxy to reduce LLM token consumption": {
|
||||
"fr": "RTK - Proxy CLI pour réduire la consommation de tokens LLM",
|
||||
"en": "RTK - CLI proxy to reduce LLM token consumption",
|
||||
},
|
||||
"Language - Change language / Changer la langue": {
|
||||
"fr": "Langue - Changer la langue / Change language",
|
||||
"en": "Language - Change language / Changer la langue",
|
||||
},
|
||||
# Deploy section
|
||||
"Deploy - Deploy ERPLibre locally": {
|
||||
"fr": "Déploiement - Déployer ERPLibre localement",
|
||||
"en": "Deploy - Deploy ERPLibre locally",
|
||||
},
|
||||
"Deploy ERPLibre to a local directory!": {
|
||||
"fr": "Déployer ERPLibre dans un répertoire local!",
|
||||
"en": "Deploy ERPLibre to a local directory!",
|
||||
},
|
||||
"Clone ERPLibre locally (git clone)": {
|
||||
"fr": "Cloner ERPLibre localement (git clone)",
|
||||
"en": "Clone ERPLibre locally (git clone)",
|
||||
},
|
||||
"Target directory path (default: ~/erplibre): ": {
|
||||
"fr": "Chemin du répertoire cible (défaut: ~/erplibre) : ",
|
||||
"en": "Target directory path (default: ~/erplibre): ",
|
||||
},
|
||||
"Directory already exists: ": {
|
||||
"fr": "Le répertoire existe déjà : ",
|
||||
"en": "Directory already exists: ",
|
||||
},
|
||||
"Cloning ERPLibre...": {
|
||||
"fr": "Clonage d'ERPLibre en cours...",
|
||||
"en": "Cloning ERPLibre...",
|
||||
},
|
||||
"ERPLibre cloned successfully to: ": {
|
||||
"fr": "ERPLibre cloné avec succès dans : ",
|
||||
"en": "ERPLibre cloned successfully to: ",
|
||||
},
|
||||
"Error cloning ERPLibre: ": {
|
||||
"fr": "Erreur lors du clonage d'ERPLibre : ",
|
||||
"en": "Error cloning ERPLibre: ",
|
||||
},
|
||||
# RTK (Rust Token Killer)
|
||||
"Manage RTK (Rust Token Killer) for token optimization!": {
|
||||
"fr": "Gérer RTK (Rust Token Killer) pour optimiser les tokens!",
|
||||
"en": "Manage RTK (Rust Token Killer) for token optimization!",
|
||||
},
|
||||
"Install RTK": {
|
||||
"fr": "Installer RTK",
|
||||
"en": "Install RTK",
|
||||
},
|
||||
"Check RTK version": {
|
||||
"fr": "Vérifier la version de RTK",
|
||||
"en": "Check RTK version",
|
||||
},
|
||||
"Show cumulative token savings": {
|
||||
"fr": "Afficher les économies de tokens cumulées",
|
||||
"en": "Show cumulative token savings",
|
||||
},
|
||||
"Discover optimization opportunities": {
|
||||
"fr": "Identifier les opportunités d'optimisation",
|
||||
"en": "Discover optimization opportunities",
|
||||
},
|
||||
"Initialize global auto-rewrite hook": {
|
||||
"fr": "Initialiser le hook auto-rewrite global",
|
||||
"en": "Initialize global auto-rewrite hook",
|
||||
},
|
||||
"Check RTK status": {
|
||||
"fr": "Vérifier le statut de RTK",
|
||||
"en": "Check RTK status",
|
||||
},
|
||||
"RTK is not installed. Use option 1 to install it.": {
|
||||
"fr": "RTK n'est pas installé. Utilisez l'option 1 pour l'installer.",
|
||||
"en": "RTK is not installed. Use option 1 to install it.",
|
||||
},
|
||||
"RTK is installed, version: ": {
|
||||
"fr": "RTK est installé, version : ",
|
||||
"en": "RTK is installed, version: ",
|
||||
},
|
||||
"Global auto-rewrite hook: active": {
|
||||
"fr": "Hook auto-rewrite global : actif",
|
||||
"en": "Global auto-rewrite hook: active",
|
||||
},
|
||||
"Global auto-rewrite hook: inactive": {
|
||||
"fr": "Hook auto-rewrite global : inactif",
|
||||
"en": "Global auto-rewrite hook: inactive",
|
||||
},
|
||||
"Installation method:": {
|
||||
"fr": "Méthode d'installation :",
|
||||
"en": "Installation method:",
|
||||
},
|
||||
"curl - Automatic install script": {
|
||||
"fr": "curl - Script d'installation automatique",
|
||||
"en": "curl - Automatic install script",
|
||||
},
|
||||
"brew - Homebrew (macOS/Linux)": {
|
||||
"fr": "brew - Homebrew (macOS/Linux)",
|
||||
"en": "brew - Homebrew (macOS/Linux)",
|
||||
},
|
||||
"cargo - Build from source (Rust required)": {
|
||||
"fr": "cargo - Compilation depuis les sources (Rust requis)",
|
||||
"en": "cargo - Build from source (Rust required)",
|
||||
},
|
||||
# Prompts and messages
|
||||
"enter_password": {
|
||||
"Enter your password: ": {
|
||||
"fr": "Entrez votre mot de passe : ",
|
||||
"en": "Enter your password: ",
|
||||
},
|
||||
"ia_prompt": {
|
||||
"Write your question ": {
|
||||
"fr": "Écrit moi ta question ",
|
||||
"en": "Write your question ",
|
||||
},
|
||||
"new_instance_confirm": {
|
||||
"Do you want a new instance?": {
|
||||
"fr": "Voulez-vous une nouvelle instance?",
|
||||
"en": "Do you want a new instance?",
|
||||
},
|
||||
"ssh_port_forwarding": {
|
||||
"SSH port-forwarding": {
|
||||
"fr": "SSH port-forwarding",
|
||||
"en": "SSH port-forwarding",
|
||||
},
|
||||
"network_performance_request_per_second": {
|
||||
"Network performance request per second": {
|
||||
"fr": "Performance réseau en requêtes par seconde",
|
||||
"en": "Network performance request per second",
|
||||
},
|
||||
"setup_queue_job_for_parallelism": {
|
||||
"Setup queue job for parallelism": {
|
||||
"fr": "Configurer la file d'attente pour l'exécution parallèle",
|
||||
"en": "Setup queue job for parallelism",
|
||||
},
|
||||
"choose_database": {
|
||||
"Choose your database": {
|
||||
"fr": "Choisir sa base de données",
|
||||
"en": "Choose your database",
|
||||
},
|
||||
"update_dev": {
|
||||
"Development update": {
|
||||
"fr": "Mise à jour du développement",
|
||||
"en": "Development update",
|
||||
},
|
||||
"code_need": {
|
||||
"What do you need for development?": {
|
||||
"fr": "Qu'avez-vous de besoin pour développer?",
|
||||
"en": "What do you need for development?",
|
||||
},
|
||||
"doc_search": {
|
||||
"Looking for documentation?": {
|
||||
"fr": "Vous cherchez de la documentation?",
|
||||
"en": "Looking for documentation?",
|
||||
},
|
||||
"db_modify": {
|
||||
"Make changes to databases!": {
|
||||
"fr": "Faites des modifications sur les bases de données!",
|
||||
"en": "Make changes to databases!",
|
||||
},
|
||||
"process_manage": {
|
||||
"Manage execution processes!": {
|
||||
"fr": "Manipuler les processus d'exécution!",
|
||||
"en": "Manage execution processes!",
|
||||
},
|
||||
"config_manage": {
|
||||
"Manage ERPLibre and Odoo configuration!": {
|
||||
"fr": "Manipuler la configuration ERPLibre et Odoo!",
|
||||
"en": "Manage ERPLibre and Odoo configuration!",
|
||||
},
|
||||
"network_tools": {
|
||||
"Network tools!": {
|
||||
"fr": "Outil réseautique!",
|
||||
"en": "Network tools!",
|
||||
},
|
||||
"security_audit": {
|
||||
"Dependency security audit!": {
|
||||
"fr": "Audit de securite des dépendances!",
|
||||
"en": "Dependency security audit!",
|
||||
},
|
||||
"script_failed": {
|
||||
"The Bash script failed with return code": {
|
||||
"fr": "Le script Bash a échoué avec le code de retour",
|
||||
"en": "The Bash script failed with return code",
|
||||
},
|
||||
"no_env_installed": {
|
||||
"No installed environment found. Install an Odoo version first.": {
|
||||
"fr": "Aucun environnement installe trouve. Installez d'abord une version d'Odoo.",
|
||||
"en": "No installed environment found. Install an Odoo version first.",
|
||||
},
|
||||
"choose_env_audit": {
|
||||
"Choose an environment for the audit:": {
|
||||
"fr": "Choisir un environnement pour l'audit :",
|
||||
"en": "Choose an environment for the audit:",
|
||||
},
|
||||
"selection": {
|
||||
"Select: ": {
|
||||
"fr": "Sélection : ",
|
||||
"en": "Select: ",
|
||||
},
|
||||
"error_value": {
|
||||
"Error, cannot understand value": {
|
||||
"fr": "Erreur, impossible de comprendre la valeur",
|
||||
"en": "Error, cannot understand value",
|
||||
},
|
||||
"dep_file_not_found": {
|
||||
"Dependencies file not found: ": {
|
||||
"fr": "Fichier de dépendances introuvable : ",
|
||||
"en": "Dependencies file not found: ",
|
||||
},
|
||||
"execution": {
|
||||
"Execution: ": {
|
||||
"fr": "Execution : ",
|
||||
"en": "Execution: ",
|
||||
},
|
||||
"current": {
|
||||
"Current": {
|
||||
"fr": "Actuel",
|
||||
"en": "Current",
|
||||
},
|
||||
"default": {
|
||||
"Default": {
|
||||
"fr": "Défaut",
|
||||
"en": "Default",
|
||||
},
|
||||
"reboot_todo": {
|
||||
"Reboot TODO ...": {
|
||||
"fr": "Reboot TODO ...",
|
||||
"en": "Reboot TODO ...",
|
||||
},
|
||||
"pip_audit_desc": {
|
||||
"pip-audit - Check vulnerabilities on Python environments": {
|
||||
"fr": "pip-audit - Verifier les vulnérabilités sur les environnements Python",
|
||||
"en": "pip-audit - Check vulnerabilities on Python environments",
|
||||
},
|
||||
"will_execute": {
|
||||
"Will execute:": {
|
||||
"fr": "Va exécuter :",
|
||||
"en": "Will execute:",
|
||||
},
|
||||
"choose_version": {
|
||||
"Choose a version:": {
|
||||
"fr": "Choisir une version :",
|
||||
"en": "Choose a version:",
|
||||
},
|
||||
"error_cannot_understand": {
|
||||
"fr": "Erreur, impossible de comprendre la valeur",
|
||||
"en": "Error, cannot understand value",
|
||||
},
|
||||
# todo.json translatable prompt_descriptions
|
||||
"json_instance_test": {
|
||||
"Test - Minimal base instance": {
|
||||
"fr": "Test - Instance de base minimale",
|
||||
"en": "Test - Minimal base instance",
|
||||
},
|
||||
"json_robot_minimal": {
|
||||
"Open RobotLibre 🤖 minimal": {
|
||||
"fr": "Ouvrir RobotLibre 🤖 minimal",
|
||||
"en": "Open RobotLibre 🤖 minimal",
|
||||
},
|
||||
"json_robot_search": {
|
||||
"Open RobotLibre 🤖 with search enabled": {
|
||||
"fr": "Ouvrir RobotLibre 🤖 en activant la recherche",
|
||||
"en": "Open RobotLibre 🤖 with search enabled",
|
||||
},
|
||||
"json_open_erplibre_todo": {
|
||||
"Open ERPLibre with TODO 🤖": {
|
||||
"fr": "Ouvrir ERPLibre avec TODO 🤖",
|
||||
"en": "Open ERPLibre with TODO 🤖",
|
||||
},
|
||||
"json_update_erplibre_base_test": {
|
||||
"Update all erplibre_base on database test": {
|
||||
"fr": "Mise à jour de tous les erplibre_base sur la base de données test",
|
||||
"en": "Update all erplibre_base on database test",
|
||||
},
|
||||
"json_show_code_status": {
|
||||
"Show code status": {
|
||||
"fr": "Afficher le statut du code",
|
||||
"en": "Show code status",
|
||||
},
|
||||
"json_stash_all_code": {
|
||||
"Stash all code": {
|
||||
"fr": "Remiser tout le code",
|
||||
"en": "Stash all code",
|
||||
},
|
||||
"json_format_modified_code": {
|
||||
"Format modified code": {
|
||||
"fr": "Formater le code modifié",
|
||||
"en": "Format modified code",
|
||||
},
|
||||
# todo.py hardcoded prompt_descriptions
|
||||
"mobile_compile_run": {
|
||||
"Mobile - Compile and run software": {
|
||||
"fr": "Mobile - Compiler et exécuter le logiciel",
|
||||
"en": "Mobile - Compile and run software",
|
||||
},
|
||||
"upgrade_odoo_migration": {
|
||||
"Upgrade Odoo - Migration Database": {
|
||||
"fr": "Mise à jour Odoo - Migration de base de données",
|
||||
"en": "Upgrade Odoo - Migration Database",
|
||||
},
|
||||
"upgrade_poetry_dependency": {
|
||||
"Upgrade Poetry - Dependency of Odoo": {
|
||||
"fr": "Mise à jour Poetry - Dépendances d'Odoo",
|
||||
"en": "Upgrade Poetry - Dependency of Odoo",
|
||||
},
|
||||
"open_shell": {
|
||||
"Open SHELL": {
|
||||
"fr": "Ouvrir le SHELL",
|
||||
"en": "Open SHELL",
|
||||
},
|
||||
"upgrade_module": {
|
||||
"Upgrade Module": {
|
||||
"fr": "Mise à jour de module",
|
||||
"en": "Upgrade Module",
|
||||
},
|
||||
"debug": {
|
||||
"Debug": {
|
||||
"fr": "Débogage",
|
||||
"en": "Debug",
|
||||
},
|
||||
"migration_module_coverage": {
|
||||
"Migration module coverage": {
|
||||
"fr": "Couverture de migration des modules",
|
||||
"en": "Migration module coverage",
|
||||
},
|
||||
"what_change_between_version": {
|
||||
"What change between version": {
|
||||
"fr": "Quels changements entre les versions",
|
||||
"en": "What change between version",
|
||||
},
|
||||
"oca_guidelines": {
|
||||
"OCA guidelines": {
|
||||
"fr": "Directives OCA",
|
||||
"en": "OCA guidelines",
|
||||
},
|
||||
"oca_migration_odoo_19": {
|
||||
"OCA migration Odoo 19 milestone": {
|
||||
"fr": "Migration OCA Odoo 19 - Jalons",
|
||||
"en": "OCA migration Odoo 19 milestone",
|
||||
},
|
||||
"download_db_backup": {
|
||||
"Download database to create backup (.zip)": {
|
||||
"fr": "Télécharger une base de données pour créer une sauvegarde (.zip)",
|
||||
"en": "Download database to create backup (.zip)",
|
||||
},
|
||||
"restore_from_backup": {
|
||||
"Restore from backup (.zip)": {
|
||||
"fr": "Restaurer a partir d'une sauvegarde (.zip)",
|
||||
"en": "Restore from backup (.zip)",
|
||||
},
|
||||
"create_backup": {
|
||||
"Create backup (.zip)": {
|
||||
"fr": "Créer une sauvegarde (.zip)",
|
||||
"en": "Create backup (.zip)",
|
||||
},
|
||||
"kill_process_port": {
|
||||
"Kill Odoo process from actual port": {
|
||||
"fr": "Terminer le processus Odoo du port actuel",
|
||||
"en": "Kill Odoo process from actual port",
|
||||
},
|
||||
"kill_git_daemon": {
|
||||
"Kill git daemon server process": {
|
||||
"fr": "Terminer le processus du serveur git daemon",
|
||||
"en": "Kill git daemon server process",
|
||||
},
|
||||
"kill_git_daemon_done": {
|
||||
"Git daemon process killed.": {
|
||||
"fr": "Processus git daemon terminé.",
|
||||
"en": "Git daemon process killed.",
|
||||
},
|
||||
"generate_all_config": {
|
||||
"Generate all configuration": {
|
||||
"fr": "Générer toute la configuration",
|
||||
"en": "Generate all configuration",
|
||||
},
|
||||
"generate_from_preconfig": {
|
||||
"Generate from pre-configuration": {
|
||||
"fr": "Générer a partir de la pre-configuration",
|
||||
"en": "Generate from pre-configuration",
|
||||
},
|
||||
"generate_from_backup": {
|
||||
"Generate from backup file": {
|
||||
"fr": "Générer a partir d'un fichier de sauvegarde",
|
||||
"en": "Generate from backup file",
|
||||
},
|
||||
"generate_from_database": {
|
||||
"Generate from database": {
|
||||
"fr": "Générer a partir de la base de données",
|
||||
"en": "Generate from database",
|
||||
},
|
||||
"preconfig_base": {
|
||||
"base": {
|
||||
"fr": "base",
|
||||
"en": "base",
|
||||
},
|
||||
"preconfig_base_code_generator": {
|
||||
"base + code_generator": {
|
||||
"fr": "base + code_generator",
|
||||
"en": "base + code_generator",
|
||||
},
|
||||
"preconfig_base_image_db": {
|
||||
"base + image_db": {
|
||||
"fr": "base + image_db",
|
||||
"en": "base + image_db",
|
||||
},
|
||||
"preconfig_all": {
|
||||
"all": {
|
||||
"fr": "tout",
|
||||
"en": "all",
|
||||
},
|
||||
"debug_todo_py": {
|
||||
"Debug todo.py": {
|
||||
"fr": "Débogage todo.py",
|
||||
"en": "Debug todo.py",
|
||||
},
|
||||
# Test section
|
||||
"menu_test": {
|
||||
"Test - Test an Odoo module": {
|
||||
"fr": "Test - Tester un module Odoo",
|
||||
"en": "Test - Test an Odoo module",
|
||||
},
|
||||
"test_description": {
|
||||
"Test an Odoo module on a temporary database!": {
|
||||
"fr": "Tester un module Odoo sur une base de données temporaire!",
|
||||
"en": "Test an Odoo module on a temporary database!",
|
||||
},
|
||||
"test_run_module": {
|
||||
"Test a module": {
|
||||
"fr": "Tester un module",
|
||||
"en": "Test a module",
|
||||
},
|
||||
"test_run_module_coverage": {
|
||||
"Test a module with code coverage": {
|
||||
"fr": "Tester un module avec couverture de code",
|
||||
"en": "Test a module with code coverage",
|
||||
},
|
||||
"test_run_unit_tests": {
|
||||
"ERPLibre unit tests": {
|
||||
"fr": "Tests unitaires ERPLibre",
|
||||
"en": "ERPLibre unit tests",
|
||||
},
|
||||
"test_unit_running": {
|
||||
"Running unit tests": {
|
||||
"fr": "Exécution des tests unitaires",
|
||||
"en": "Running unit tests",
|
||||
},
|
||||
"test_unit_success": {
|
||||
"All unit tests passed": {
|
||||
"fr": "Tous les tests unitaires ont réussi",
|
||||
"en": "All unit tests passed",
|
||||
},
|
||||
"test_unit_failed": {
|
||||
"Some unit tests failed, exit code": {
|
||||
"fr": "Des tests unitaires ont échoué, code de sortie",
|
||||
"en": "Some unit tests failed, exit code",
|
||||
},
|
||||
"test_enter_module_name": {
|
||||
"Module name to test: ": {
|
||||
"fr": "Nom du module à tester : ",
|
||||
"en": "Module name to test: ",
|
||||
},
|
||||
"test_db_name": {
|
||||
"Temporary database name (default: test_todo_tmp): ": {
|
||||
"fr": "Nom de la base de données temporaire (défaut: test_todo_tmp) : ",
|
||||
"en": "Temporary database name (default: test_todo_tmp): ",
|
||||
},
|
||||
"test_install_extra_modules": {
|
||||
"Extra modules to install (comma-separated, empty for none): ": {
|
||||
"fr": "Modules supplémentaires à installer (séparés par des virgules, vide pour aucun) : ",
|
||||
"en": "Extra modules to install (comma-separated, empty for none): ",
|
||||
},
|
||||
"test_log_level": {
|
||||
"Log level (default: test): ": {
|
||||
"fr": "Niveau de log (défaut: test) : ",
|
||||
"en": "Log level (default: test): ",
|
||||
},
|
||||
"test_creating_db": {
|
||||
"Creating temporary database": {
|
||||
"fr": "Création de la base de données temporaire",
|
||||
"en": "Creating temporary database",
|
||||
},
|
||||
"test_installing_modules": {
|
||||
"Installing modules": {
|
||||
"fr": "Installation des modules",
|
||||
"en": "Installing modules",
|
||||
},
|
||||
"test_running": {
|
||||
"Running tests": {
|
||||
"fr": "Exécution des tests",
|
||||
"en": "Running tests",
|
||||
},
|
||||
"test_cleaning_db": {
|
||||
"Cleaning up temporary database": {
|
||||
"fr": "Suppression de la base de données temporaire",
|
||||
"en": "Cleaning up temporary database",
|
||||
},
|
||||
"test_keep_db": {
|
||||
"Keep the temporary database? (y/N): ": {
|
||||
"fr": "Conserver la base de données temporaire? (o/N) : ",
|
||||
"en": "Keep the temporary database? (y/N): ",
|
||||
},
|
||||
"test_db_kept": {
|
||||
"Database kept": {
|
||||
"fr": "Base de données conservée",
|
||||
"en": "Database kept",
|
||||
},
|
||||
"test_success": {
|
||||
"Tests completed successfully!": {
|
||||
"fr": "Tests terminés avec succès!",
|
||||
"en": "Tests completed successfully!",
|
||||
},
|
||||
"test_failed": {
|
||||
"Tests failed with return code": {
|
||||
"fr": "Les tests ont échoué avec le code de retour",
|
||||
"en": "Tests failed with return code",
|
||||
},
|
||||
"test_module_required": {
|
||||
"Module name is required!": {
|
||||
"fr": "Le nom du module est requis!",
|
||||
"en": "Module name is required!",
|
||||
},
|
||||
# Git section
|
||||
"menu_git": {
|
||||
"Git - Git tools": {
|
||||
"fr": "Git - Outils Git",
|
||||
"en": "Git - Git tools",
|
||||
},
|
||||
"git_manage": {
|
||||
"Git management tools!": {
|
||||
"fr": "Outils de gestion Git!",
|
||||
"en": "Git management tools!",
|
||||
},
|
||||
"git_local_server": {
|
||||
"Local git server": {
|
||||
"fr": "Serveur git local",
|
||||
"en": "Local git server",
|
||||
},
|
||||
"git_repo_manage": {
|
||||
"Manage local git repository server!": {
|
||||
"fr": "Gérer le serveur de dépôts git local!",
|
||||
"en": "Manage local git repository server!",
|
||||
},
|
||||
"git_repo_deploy_local": {
|
||||
"Deploy a local git server (~/.git-server)": {
|
||||
"fr": "Déployer un serveur git local (~/.git-server)",
|
||||
"en": "Deploy a local git server (~/.git-server)",
|
||||
},
|
||||
"git_repo_deploy_production": {
|
||||
"Deploy a production git server (/srv/git, root required)": {
|
||||
"fr": "Déployer un serveur git production (/srv/git, root requis)",
|
||||
"en": "Deploy a production git server (/srv/git, root required)",
|
||||
},
|
||||
"git_repo_deploy_starting": {
|
||||
"Starting git server deployment...": {
|
||||
"fr": "Démarrage du déploiement du serveur git...",
|
||||
"en": "Starting git server deployment...",
|
||||
},
|
||||
"git_mode_local": {
|
||||
"Local mode (~/.git-server)": {
|
||||
"fr": "Mode local (~/.git-server)",
|
||||
"en": "Local mode (~/.git-server)",
|
||||
},
|
||||
"git_mode_production": {
|
||||
"Production mode (/srv/git, root required)": {
|
||||
"fr": "Mode production (/srv/git, root requis)",
|
||||
"en": "Production mode (/srv/git, root required)",
|
||||
},
|
||||
"git_action_all": {
|
||||
"Run all (init + remote + push + serve)": {
|
||||
"fr": "Tout exécuter (init + remote + push + serve)",
|
||||
"en": "Run all (init + remote + push + serve)",
|
||||
},
|
||||
"git_action_init": {
|
||||
"Init - Create bare repos": {
|
||||
"fr": "Init - Créer les bare repos",
|
||||
"en": "Init - Create bare repos",
|
||||
},
|
||||
"git_action_remote": {
|
||||
"Remote - Add local remotes": {
|
||||
"fr": "Remote - Ajouter les remotes locaux",
|
||||
"en": "Remote - Add local remotes",
|
||||
},
|
||||
"git_action_push": {
|
||||
"Push - Push to local server": {
|
||||
"fr": "Push - Pousser vers le serveur local",
|
||||
"en": "Push - Push to local server",
|
||||
},
|
||||
"git_action_serve": {
|
||||
"Serve - Start git daemon": {
|
||||
"fr": "Serve - Démarrer le daemon git",
|
||||
"en": "Serve - Start git daemon",
|
||||
},
|
||||
# Git remote add
|
||||
"Add a remote to a local repository": {
|
||||
"fr": "Ajouter un remote vers un dépôt local",
|
||||
"en": "Add a remote to a local repository",
|
||||
},
|
||||
"Remote name (default: localhost): ": {
|
||||
"fr": "Nom du remote (défaut: localhost) : ",
|
||||
"en": "Remote name (default: localhost): ",
|
||||
},
|
||||
"Repository address (e.g.: git://192.168.1.100/my-repo.git): ": {
|
||||
"fr": "Adresse du dépôt (ex: git://192.168.1.100/mon-repo.git) : ",
|
||||
"en": "Repository address (e.g.: git://192.168.1.100/my-repo.git): ",
|
||||
},
|
||||
"Repository address is required!": {
|
||||
"fr": "L'adresse du dépôt est requise!",
|
||||
"en": "Repository address is required!",
|
||||
},
|
||||
"Remote added successfully!": {
|
||||
"fr": "Remote ajouté avec succès!",
|
||||
"en": "Remote added successfully!",
|
||||
},
|
||||
"Error adding remote: ": {
|
||||
"fr": "Erreur lors de l'ajout du remote : ",
|
||||
"en": "Error adding remote: ",
|
||||
},
|
||||
# Git config vim
|
||||
"Configure git local editor to vim": {
|
||||
"fr": "Configuration git local par vim",
|
||||
"en": "Configure git local editor to vim",
|
||||
},
|
||||
"Git editor configured to vim successfully!": {
|
||||
"fr": "Éditeur git configuré sur vim avec succès!",
|
||||
"en": "Git editor configured to vim successfully!",
|
||||
},
|
||||
"Error during configuration: ": {
|
||||
"fr": "Erreur lors de la configuration : ",
|
||||
"en": "Error during configuration: ",
|
||||
},
|
||||
# GPT code - Claude automation
|
||||
"Add an automation with Claude in todo.py": {
|
||||
"fr": "Ajouter une automatisation avec Claude dans todo.py",
|
||||
"en": "Add an automation with Claude in todo.py",
|
||||
},
|
||||
"Description of the command to add: ": {
|
||||
"fr": "Description de la commande à ajouter : ",
|
||||
"en": "Description of the command to add: ",
|
||||
},
|
||||
"Bash command to execute: ": {
|
||||
"fr": "Commande bash à exécuter : ",
|
||||
"en": "Bash command to execute: ",
|
||||
},
|
||||
"Menu section (git/code/config/network/process): ": {
|
||||
"fr": "Section du menu (git/code/config/network/process) : ",
|
||||
"en": "Menu section (git/code/config/network/process): ",
|
||||
},
|
||||
"Automation added successfully in todo.json!": {
|
||||
"fr": "Automatisation ajoutée avec succès dans todo.json!",
|
||||
"en": "Automation added successfully in todo.json!",
|
||||
},
|
||||
"Error adding automation: ": {
|
||||
"fr": "Erreur lors de l'ajout de l'automatisation : ",
|
||||
"en": "Error adding automation: ",
|
||||
},
|
||||
# Language selection
|
||||
"lang_prompt": {
|
||||
"Choose language / Choisir la langue": {
|
||||
"fr": "Choisir la langue / Choose language",
|
||||
"en": "Choose language / Choisir la langue",
|
||||
},
|
||||
"lang_french": {
|
||||
"French": {
|
||||
"fr": "Francais",
|
||||
"en": "French",
|
||||
},
|
||||
"lang_english": {
|
||||
"English": {
|
||||
"fr": "Anglais",
|
||||
"en": "English",
|
||||
},
|
||||
"lang_changed": {
|
||||
"Language changed to: English": {
|
||||
"fr": "Langue changée pour : Francais",
|
||||
"en": "Language changed to: English",
|
||||
},
|
||||
"execution_time": {
|
||||
"TODO execution time": {
|
||||
"fr": "Temps d'exécution TODO",
|
||||
"en": "TODO execution time",
|
||||
},
|
||||
"keyboard_interrupt": {
|
||||
"Keyboard interrupt": {
|
||||
"fr": "Interruption clavier",
|
||||
"en": "Keyboard interrupt",
|
||||
},
|
||||
# GPT code section
|
||||
"menu_gpt_code": {
|
||||
"GPT code - AI assistant tools": {
|
||||
"fr": "GPT code - Outils d'assistant IA",
|
||||
"en": "GPT code - AI assistant tools",
|
||||
},
|
||||
"gpt_code_manage": {
|
||||
"AI assistant tools for development!": {
|
||||
"fr": "Outils d'assistant IA pour le développement!",
|
||||
"en": "AI assistant tools for development!",
|
||||
},
|
||||
"gpt_code_claude_commit": {
|
||||
"fr": "Configurer le commit Claude Code",
|
||||
"en": "Configure Claude Code commit",
|
||||
"Configure Claude Code configurations": {
|
||||
"fr": "Configurer les configurations Claude Code",
|
||||
"en": "Configure Claude Code configurations",
|
||||
},
|
||||
"gpt_code_enter_name": {
|
||||
"Commit - OCA/Odoo commit command": {
|
||||
"fr": "Commit - Commande de commit OCA/Odoo",
|
||||
"en": "Commit - OCA/Odoo commit command",
|
||||
},
|
||||
"Todo Add Command - Add a command to todo.py menu": {
|
||||
"fr": "Todo Add Command - Ajouter une commande au menu todo.py",
|
||||
"en": "Todo Add Command - Add a command to todo.py menu",
|
||||
},
|
||||
"Enter your full name: ": {
|
||||
"fr": "Entrez votre nom complet : ",
|
||||
"en": "Enter your full name: ",
|
||||
},
|
||||
"gpt_code_enter_email": {
|
||||
"Enter your email: ": {
|
||||
"fr": "Entrez votre courriel : ",
|
||||
"en": "Enter your email: ",
|
||||
},
|
||||
"gpt_code_commit_exists": {
|
||||
"fr": "Le fichier ~/.claude/commands/commit.md existe déjà. Aucune action effectuée.",
|
||||
"en": "File ~/.claude/commands/commit.md already exists. No action taken.",
|
||||
"Deploy Claude Code commands!": {
|
||||
"fr": "Déployer les commandes Claude Code!",
|
||||
"en": "Deploy Claude Code commands!",
|
||||
},
|
||||
"gpt_code_commit_created": {
|
||||
"fr": "Fichier ~/.claude/commands/commit.md créé avec succès!",
|
||||
"en": "File ~/.claude/commands/commit.md created successfully!",
|
||||
"Show installed custom commands": {
|
||||
"fr": "Afficher les commandes personnalisées installées",
|
||||
"en": "Show installed custom commands",
|
||||
},
|
||||
"gpt_code_commit_error": {
|
||||
"No custom commands found in ~/.claude/commands/": {
|
||||
"fr": "Aucune commande personnalisée trouvée dans ~/.claude/commands/",
|
||||
"en": "No custom commands found in ~/.claude/commands/",
|
||||
},
|
||||
"Claude Code custom commands:": {
|
||||
"fr": "Commandes personnalisées Claude Code :",
|
||||
"en": "Claude Code custom commands:",
|
||||
},
|
||||
"Total:": {
|
||||
"fr": "Total :",
|
||||
"en": "Total:",
|
||||
},
|
||||
"File already exists: ": {
|
||||
"fr": "Le fichier existe déjà : ",
|
||||
"en": "File already exists: ",
|
||||
},
|
||||
"Do you want to overwrite the file? (y/Y): ": {
|
||||
"fr": "Voulez-vous écraser le fichier? (y/Y) : ",
|
||||
"en": "Do you want to overwrite the file? (y/Y): ",
|
||||
},
|
||||
"Nothing to do.": {
|
||||
"fr": "Rien à faire.",
|
||||
"en": "Nothing to do.",
|
||||
},
|
||||
"File created successfully: ": {
|
||||
"fr": "Fichier créé avec succès : ",
|
||||
"en": "File created successfully: ",
|
||||
},
|
||||
"Error creating file: ": {
|
||||
"fr": "Erreur lors de la création du fichier : ",
|
||||
"en": "Error creating file: ",
|
||||
},
|
||||
|
|
|
|||
Loading…
Reference in a new issue