Système de gestion de traductions pensé en CMS headless : un back-office pour ceux qui traduisent, une API pour ce qui consomme. Architecture - Symfony 7.4 / API Platform 4.3 / MariaDB 11.4, SPA React 19 servie en même origine — ce qui rend viable le cookie de session plutôt qu'un jeton en localStorage. - Deux APIs séparées : Management (session ou clé) et Delivery (stateless, clé seule). Les fusionner ferait porter à chaque lecture de bundle le coût de la session. - Stockage canonique en ICU MessageFormat, sérialisation par plateforme. Le format d'une plateforme ne contamine pas la base. - Publication par releases immuables ; le déploiement est un déplacement de pointeur, donc le rollback aussi. - Isolation multi-organisation par filtre Doctrine, avec un test d'architecture qui casse la CI si une entité échappe à l'invariant. Éditeur, deux vues - Par langue : source et cible, jamais douze colonnes. Grille virtualisée, saisie sans bouton « Enregistrer », panneau de contexte permanent. - Par clé : une clé, toutes ses langues empilées et repliées. Répond à « ce libellé est-il prêt partout ? ». - Mode Focus dans les deux : une file à vider, ⌘↵ pour enchaîner. - Le traducteur ne voit jamais d'ICU : pastilles de variables, un champ par catégorie CLDR de la langue cible. Administration - Deux niveaux : projet (membres, clés API, plateformes) et organisation (annuaire des comptes, création de projets). - Invitations par e-mail, jeton 256 bits stocké haché. - Désactiver un compte coupe les sessions en cours, pas seulement les connexions suivantes. - Les plateformes s'archivent ; ni elles ni les environnements ne se suppriment — la trace explique pourquoi telle clé existe. CLI tqs - PHAR autonome de 3 Mo, autoloader généré : le dépôt client ne dépend ni de Composer ni de la disponibilité de TQ-Slator. - init / push / pull / status ; le sync est non destructif par défaut et son prune est scopé plateforme. 126 tests, PHPStan niveau 8. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
106 lines
3.1 KiB
JSON
106 lines
3.1 KiB
JSON
{
|
|
"name": "tranquilys/tq-slator",
|
|
"description": "TQ-Slator — Translation Management System headless",
|
|
"type": "project",
|
|
"license": "proprietary",
|
|
"minimum-stability": "stable",
|
|
"prefer-stable": true,
|
|
"require": {
|
|
"php": ">=8.3",
|
|
"ext-ctype": "*",
|
|
"ext-iconv": "*",
|
|
"ext-intl": "*",
|
|
"ext-json": "*",
|
|
"ext-mbstring": "*",
|
|
"ext-pdo": "*",
|
|
"api-platform/doctrine-orm": "^4.3",
|
|
"api-platform/symfony": "^4.3",
|
|
"doctrine/doctrine-bundle": "^3.3",
|
|
"doctrine/doctrine-migrations-bundle": "^4.0",
|
|
"doctrine/orm": "^3.6",
|
|
"nelmio/cors-bundle": "^2.6",
|
|
"runtime/frankenphp-symfony": "^1.0",
|
|
"symfony/console": "7.4.*",
|
|
"symfony/doctrine-messenger": "7.4.*",
|
|
"symfony/dotenv": "7.4.*",
|
|
"symfony/expression-language": "7.4.*",
|
|
"symfony/flex": "^2",
|
|
"symfony/framework-bundle": "7.4.*",
|
|
"symfony/http-client": "7.4.*",
|
|
"symfony/mailer": "7.4.*",
|
|
"symfony/messenger": "7.4.*",
|
|
"symfony/monolog-bundle": "^4.0",
|
|
"symfony/property-access": "7.4.*",
|
|
"symfony/property-info": "7.4.*",
|
|
"symfony/rate-limiter": "7.4.*",
|
|
"symfony/runtime": "7.4.*",
|
|
"symfony/security-bundle": "7.4.*",
|
|
"symfony/serializer": "7.4.*",
|
|
"symfony/twig-bundle": "7.4.*",
|
|
"symfony/uid": "7.4.*",
|
|
"symfony/validator": "7.4.*",
|
|
"symfony/yaml": "7.4.*"
|
|
},
|
|
"config": {
|
|
"allow-plugins": {
|
|
"php-http/discovery": true,
|
|
"symfony/flex": true,
|
|
"symfony/runtime": true,
|
|
"phpstan/extension-installer": true
|
|
},
|
|
"platform": {
|
|
"php": "8.4.0"
|
|
},
|
|
"sort-packages": true
|
|
},
|
|
"autoload": {
|
|
"psr-4": {
|
|
"App\\": "src/"
|
|
}
|
|
},
|
|
"autoload-dev": {
|
|
"psr-4": {
|
|
"App\\Tests\\": "tests/"
|
|
}
|
|
},
|
|
"replace": {
|
|
"symfony/polyfill-ctype": "*",
|
|
"symfony/polyfill-iconv": "*",
|
|
"symfony/polyfill-intl-grapheme": "*",
|
|
"symfony/polyfill-intl-normalizer": "*",
|
|
"symfony/polyfill-mbstring": "*"
|
|
},
|
|
"scripts": {
|
|
"auto-scripts": {
|
|
"cache:clear": "symfony-cmd",
|
|
"assets:install %PUBLIC_DIR%": "symfony-cmd"
|
|
},
|
|
"post-install-cmd": [
|
|
"@auto-scripts"
|
|
],
|
|
"post-update-cmd": [
|
|
"@auto-scripts"
|
|
]
|
|
},
|
|
"conflict": {
|
|
"symfony/symfony": "*"
|
|
},
|
|
"extra": {
|
|
"symfony": {
|
|
"allow-contrib": false,
|
|
"require": "7.4.*"
|
|
}
|
|
},
|
|
"require-dev": {
|
|
"doctrine/doctrine-fixtures-bundle": "^4.3",
|
|
"friendsofphp/php-cs-fixer": "^3.95",
|
|
"phpstan/extension-installer": "^1.4",
|
|
"phpstan/phpstan": "^2.2",
|
|
"phpstan/phpstan-doctrine": "^2.0",
|
|
"phpstan/phpstan-symfony": "^2.0",
|
|
"phpunit/phpunit": "^12.5",
|
|
"symfony/browser-kit": "7.4.*",
|
|
"symfony/css-selector": "7.4.*",
|
|
"symfony/maker-bundle": "^1.67"
|
|
}
|
|
}
|