feat(pages): generate Phases 8-11 — Technology + Editorial + Forms + Home

Brings the site to its full programmatic page count : 24 EN + 24 FR pages
(48 total), all wired into the WPML CTE workflow established in the previous
commit. Each phase reuses tools/_av-bricks-shared.php builders, adds its own
filter('av_fr_translation_dict') to extend the FR dictionary, and ships a
seed-FR mu-plugin for the initial WPML trid linking.

## Phase 8 — Technology (tools/av-generate-technology.php + seed)
Hub /technology/ + 6 pillar pages (vr-hardware, software-ai, weapons-tracking,
scenarios, instructor-cockpit, after-action-review). Hub uses a 6-card grid
(3+3 layout — added card_count=6 case in av_build_cards_section).
EN : 87-93. FR : 94-100.

## Phase 9 — Editorial (tools/av-generate-editorial.php + seed)
5 top-level pages : /why-asterion/, /about/, /customers/, /trust/, /partners/.
Required adding empty-parent-path support to av_upsert_detail_page() so pages
can be created at the site root (no hub). EN : 107-111. FR : 112-116.

## Phase 10 — Forms (tools/av-generate-forms.php + seed)
4 conversion pages : /request-demo/, /request-te-kit/, /request-quote/,
/contact/. Custom page builder (not the shared detail-page pattern) :
hero + 2-column section (Bricks `form` element on left, promise list on
right) + optional shortcuts row (Contact), eligibility list (T&E Kit), FAQ
accordion (Demo). Form actions=email, emailTo=hello@asterionvr.com.
Field labels, select options, FAQ Q&A all in the FR dict.
EN : 122-125. FR : 126-129.

## Phase 11 — Home page (tools/av-generate-home.php + seed)
Custom-written single page (no data file). Sections : hero + 3-pillar cards
(Operational reality / Modular / Sovereign) + 4 Industries cards + 4
Solutions cards + 4-stat numbers band + Why-Asterion teaser CTA + Customers
teaser CTA + custom navy closer. Set as WP static front via
update_option(show_on_front=page, page_on_front=ID).
EN : 134. FR : 135.

## tools/_av-bricks-shared.php
- av_upsert_detail_page() now accepts empty `$parent_path` → top-level page
- av_build_cards_section() handles card_count=6 → 3-per-row layout

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-14 19:58:48 +02:00
parent d2badf49d4
commit 38c0c5031e
9 changed files with 1500 additions and 6 deletions

View File

@@ -0,0 +1,172 @@
<?php
/**
* Plugin Name: Asterion — Generate editorial pages (one-shot)
* Description: /?av_generate_editorial=1 reads content-source/editorial-data.php
* and creates/updates 5 top-level pages : /why-asterion/, /about/, /customers/,
* /trust/, /partners/. No hub — each page is independent at the site root.
*/
defined('ABSPATH') || exit;
require_once __DIR__ . '/_av-bricks-shared.php';
/* -----------------------------------------------------------------
Register Editorial-specific FR strings into the shared dict.
----------------------------------------------------------------- */
add_filter('av_fr_translation_dict', function ($dict) {
return array_merge($dict, av_editorial_fr_dict());
});
function av_editorial_fr_dict() {
return [
/* ============================ Why Asterion ============================ */
'Why Asterion' => 'Pourquoi Asterion',
'A platform built around the operator. Not the other way around.'
=> "Une plateforme construite autour de l'opérateur. Pas l'inverse.",
"Asterion VR was founded in 2016 to solve one specific problem: security forces need more repetition than the ranges, ammunition budgets, and exercise calendars allow. Ten years later, the platform we built does exactly that \u{2014} at every scale, in every environment, for every role."
=> "Asterion VR a été fondé en 2016 pour résoudre un problème précis : les forces de sécurité ont besoin de plus de répétition que ce que les stands, les budgets munitions et les calendriers d'exercice permettent. Dix ans plus tard, la plateforme que nous avons construite fait exactement cela \u{2014} à toute échelle, dans tout environnement, pour tout rôle.",
'Read our customer stories' => 'Lisez nos retours clients',
'Meet the team' => "Rencontrez l'équipe",
'What makes us different' => 'Ce qui nous différencie',
'Six commitments engineered into the platform.' => 'Six engagements gravés dans la plateforme.',
'French-engineered, EU-sovereign' => 'Conçu en France, souverain européen',
'Designed and produced in France. Software developed in our French studio. Operates fully offline. No data leaves your network. No foreign cloud dependency. No ITAR exposure. GDPR-native by default.'
=> "Conçu et produit en France. Logiciel développé dans notre studio français. Fonctionne entièrement hors ligne. Aucune donnée ne quitte votre réseau. Aucune dépendance à un cloud étranger. Aucune exposition ITAR. RGPD-natif par défaut.",
'Modular from day one' => 'Modulaire dès le premier jour',
'MY PROSERVE, FLEX, ACADEMY \u{2014} same software, same scenarios, same instructor tools, three deployment formats. Start solo. Add operators. Scale to a full academy. Your investment never resets.'
=> "MY PROSERVE, FLEX, ACADEMY \u{2014} même logiciel, mêmes scénarios, mêmes outils instructeur, trois formats de déploiement. Commencez seul. Ajoutez des opérateurs. Passez à l'académie complète. Votre investissement ne repart jamais à zéro.",
'Real-recoil weapon integration' => 'Intégration d\'armes à recul réel',
'Train with the weapon you carry. Our Universal Weapon Digitizer attaches to gas-blowback replicas, CO2 replicas, or real service weapons firing blanks. Recoil is real. Tracking survives recoil. Muscle memory transfers.'
=> "Entraînez-vous avec l'arme que vous portez. Notre Universal Weapon Digitizer s'attache aux répliques gas-blowback, CO2, ou aux vraies armes de service à blanc. Le recul est réel. Le tracking survit au recul. La mémoire musculaire transfère.",
'Behavior, not scripts' => 'Du comportement, pas du script',
'AI civilians and adversaries with vision, hearing, and configurable personality. Same starting conditions, different outcomes. Trainees train against decisions, not pattern recognition.'
=> "Civils et adversaires IA avec vision, ouïe et personnalité configurable. Mêmes conditions de départ, issues différentes. Les stagiaires s'entraînent contre des décisions, pas la reconnaissance de patterns.",
'Instructor-first, not trainee-first' => 'Instructeur d\'abord, stagiaire ensuite',
'Most VR products are built for the headset wearer. We built ours for the instructor \u{2014} because the instructor is the one who turns immersion into learning.'
=> "La plupart des produits VR sont construits pour celui qui porte le casque. Nous avons construit le nôtre pour l'instructeur \u{2014} car c'est l'instructeur qui transforme l'immersion en apprentissage.",
'AAR redefined' => 'L\'AAR redéfini',
'Frame-level replay. Per-trainee statistics. Unit-level dashboards. Comparable across time. Exportable to your reporting systems. Every drill ends measurable.'
=> "Rejeu image par image. Statistiques par stagiaire. Tableaux de bord par unité. Comparable dans le temps. Exportable vers vos systèmes de reporting. Chaque exercice se termine mesurable.",
'Where we come from' => "D'où nous venons",
'The thread of Ariadne.' => "Le fil d'Ariane.",
"Asterion is the original Greek name of the Minotaur \u{2014} the creature that lived at the heart of Daedalus's labyrinth. He was confronted by Theseus, who survived by training, intelligence, and the thread of Ariadne. The name we carry is a reminder: in the labyrinth of contemporary security operations, training is the thread that brings operators home."
=> "Asterion est le nom grec d'origine du Minotaure \u{2014} la créature qui vivait au c\u{153}ur du labyrinthe de Dédale. Il fut affronté par Thésée, qui survécut grâce à l'entraînement, l'intelligence et le fil d'Ariane. Le nom que nous portons est un rappel : dans le labyrinthe des opérations de sécurité contemporaines, l'entraînement est le fil qui ramène les opérateurs chez eux.",
'The numbers' => 'Les chiffres',
'Asterion VR in figures.' => 'Asterion VR en chiffres.',
/* ============================ About ============================ */
'About' => 'À propos',
'Built in France, for forces that train where it counts.'
=> "Construit en France, pour les forces qui s'entraînent là où ça compte.",
"Asterion VR was founded in 2016 by J\u{E9}r\u{F4}me Foucher and a small team convinced of one thing: that the gap between regulation and reality in security forces training would not close on its own."
=> "Asterion VR a été fondé en 2016 par Jérôme Foucher et une petite équipe convaincue d'une chose : que l'écart entre la réglementation et la réalité dans la formation des forces de sécurité ne se refermerait pas tout seul.",
'The conviction' => 'La conviction',
'In 2016, we looked at the numbers.' => 'En 2016, nous avons regardé les chiffres.',
'French police regulation required 90 cartridges per officer per year. The actual median was between 10 and 15. Tactical errors under stress increased by 40% compared to baseline conditions. 42% of intervention errors were linked to insufficient realistic preparation. The infrastructure to fix this \u{2014} saturated ranges, expensive live exercises, finite instructor time \u{2014} was not going to expand. Something had to change in the methodology. VR was the obvious answer. But the VR available in 2016 was built for entertainment. The recoil was fake. The civilians were on rails. The instructor saw what the trainee saw. The data was nowhere. We started over.'
=> "La réglementation police française exigeait 90 cartouches par agent et par an. La médiane réelle était entre 10 et 15. Les erreurs tactiques sous stress augmentaient de 40% par rapport aux conditions de base. 42% des erreurs d'intervention étaient liées à une préparation réaliste insuffisante. L'infrastructure pour y remédier \u{2014} stands saturés, exercices réels coûteux, temps instructeur limité \u{2014} n'allait pas s'étendre. Quelque chose devait changer dans la méthode. La VR était la réponse évidente. Mais la VR disponible en 2016 était construite pour le divertissement. Le recul était factice. Les civils sur rails. L'instructeur voyait ce que voyait le stagiaire. Les données nulle part. Nous avons recommencé.",
'Ten years of one focus' => 'Dix ans, une seule mission',
'Security forces. Nothing else.' => 'Forces de sécurité. Rien d\'autre.',
'Asterion has never built a single product for entertainment, education, or industry. Our entire roadmap, from day one, has been the training of security forces. Every iteration of our weapon tracker, every line of code in our AI engine, every environment in our scenario library was specified by serving or former operators.'
=> "Asterion n'a jamais construit le moindre produit pour le divertissement, l'éducation ou l'industrie. Notre feuille de route entière, dès le premier jour, c'est la formation des forces de sécurité. Chaque itération de notre tracker d'arme, chaque ligne de code de notre moteur IA, chaque environnement de notre bibliothèque de scénarios a été spécifié par des opérateurs en service ou anciens.",
'The team' => 'L\'équipe',
'Engineers, operators, designers.' => 'Ingénieurs, opérateurs, designers.',
'Asterion in your network' => 'Asterion dans votre réseau',
'Members and partners.' => 'Membres et partenaires.',
'We are members of the French defense innovation cluster, the French Tech ecosystem, and active partners with HTC VIVE Business and Unreal Engine programmes for defense and public sector applications. We work with a network of distributors and integrators across Europe, the Middle East, and Asia.'
=> "Nous sommes membres du cluster français d'innovation défense, de l'écosystème French Tech, et partenaires actifs des programmes HTC VIVE Business et Unreal Engine pour les applications défense et secteur public. Nous travaillons avec un réseau de distributeurs et d'intégrateurs en Europe, au Moyen-Orient et en Asie.",
/* ============================ Customers ============================ */
'Customers & Case Studies' => 'Clients & retours d\'expérience',
'Customers' => 'Clients',
'Real deployments. Measured results.' => 'Déploiements réels. Résultats mesurés.',
'PROSERVE is in active service with police, gendarmerie, and tactical units across Europe. Some are public references. Some operate under nondisclosure agreements. The case studies below show \u{2014} under their own names, with their own metrics, in their own words \u{2014} how they train with us.'
=> "PROSERVE est en service actif auprès de polices, gendarmeries et unités tactiques à travers l'Europe. Certaines sont des références publiques. Certaines opèrent sous accord de confidentialité. Les retours d'expérience ci-dessous montrent \u{2014} sous leur nom, avec leurs propres métriques, dans leurs propres mots \u{2014} comment ils s'entraînent avec nous.",
'Become the next case study' => 'Devenez le prochain retour d\'expérience',
'Featured case studies' => 'Retours d\'expérience phares',
'Sample deployments \u{2014} to be detailed in /customers/[slug]/.'
=> "Déploiements types \u{2014} à détailler dans /customers/[slug]/.",
'National police academy, France' => 'École nationale de police, France',
'Continuous marksmanship training across 12 stations. 1500 officers trained in the first 18 months. Per-officer median annual cartridge count rose from 14 to 117 (live + simulated). Tactical-error rate on benchmark drill dropped 35%.'
=> "Entraînement tir continu sur 12 stations. 1500 agents formés dans les 18 premiers mois. Le nombre médian annuel de cartouches par agent est passé de 14 à 117 (réel + simulé). Le taux d'erreur tactique sur drill de référence a baissé de 35%.",
'Regional gendarmerie tactical unit' => 'Unité tactique de gendarmerie régionale',
'PROSERVE FLEX deployed for forward training during multi-week field rotations. Hostage-rescue drill repetition multiplied by 8 over 6 months. Reaction time under contact improved 22% on benchmark drill.'
=> "PROSERVE FLEX déployé pour entraînement avancé pendant des rotations terrain pluri-hebdomadaires. Répétition du drill de libération d'otages multipliée par 8 sur 6 mois. Temps de réaction sous contact amélioré de 22% sur le drill de référence.",
'Municipal police, large city' => 'Police municipale, grande ville',
'MY PROSERVE rolled out to 24 stations. Self-reported training confidence improved 41%. Continuous-training compliance rose from 38% to 92% within 12 months.'
=> "MY PROSERVE déployé sur 24 postes. La confiance en formation auto-déclarée s'est améliorée de 41%. La conformité à la formation continue est passée de 38% à 92% en 12 mois.",
'Firefighter regional training centre' => 'Centre régional de formation des sapeurs-pompiers',
'PROSERVE ACADEMY-FLEX hybrid for hazmat and confined-space rescue. Annual exercise volume tripled. Recruit retention improved due to better preparation for live exercise.'
=> "Hybride PROSERVE ACADEMY-FLEX pour interventions matières dangereuses et espaces confinés. Volume annuel d'exercice triplé. Rétention des recrues améliorée grâce à une meilleure préparation aux exercices réels.",
'Reference partners' => 'Partenaires de référence',
'If your unit is interested in becoming a public reference.' => 'Si votre unité souhaite devenir une référence publique.',
'We work with reference partners on a long-term basis. In exchange for the right to publish your story (with the level of detail you authorize), we offer extended support, priority on custom scenarios, and active involvement in our product roadmap. Reach out to discuss.'
=> "Nous travaillons avec les partenaires de référence sur le long terme. En échange du droit de publier votre histoire (au niveau de détail que vous autorisez), nous offrons un support étendu, la priorité sur les scénarios sur mesure et une implication active dans notre feuille de route produit. Contactez-nous pour en discuter.",
/* ============================ Trust ============================ */
'Trust & Compliance' => 'Confiance & conformité',
'Trust by engineering, not by claim.' => 'La confiance par l\'ingénierie, pas par l\'affirmation.',
'Asterion VR is engineered for the trust requirements of public security forces. Sovereignty, data protection, and operational autonomy are designed into the platform \u{2014} not bolted on for compliance.'
=> "Asterion VR est conçu pour les exigences de confiance des forces de sécurité publiques. Souveraineté, protection des données et autonomie opérationnelle sont intégrées à la plateforme \u{2014} pas plaquées pour la conformité.",
'Request a Trust Pack' => 'Demander un Trust Pack',
'Sovereignty' => 'Souveraineté',
'Designed European, supported European.' => 'Conçu européen, supporté européen.',
'Data protection' => 'Protection des données',
'Your data never leaves your network.' => 'Vos données ne quittent jamais votre réseau.',
'Operational autonomy' => 'Autonomie opérationnelle',
'Train without an internet connection.' => 'Entraînez-vous sans connexion internet.',
'Cyber posture' => 'Posture cyber',
'Hardened for institutional environments.' => 'Durci pour les environnements institutionnels.',
'Warranty & support' => 'Garantie & support',
'Perpetual licenses. Predictable support.' => 'Licences perpétuelles. Support prévisible.',
/* ============================ Partners ============================ */
'Partners' => 'Partenaires',
'Distribute PROSERVE in your region.' => 'Distribuez PROSERVE dans votre région.',
'Asterion partners with established defense, security, and integrator companies across Europe, the Middle East, Asia, and Latin America. Our partner network combines local presence with our French engineering and studio. We are looking for new partners in selected regions.'
=> "Asterion s'associe à des entreprises établies dans la défense, la sécurité et l'intégration en Europe, au Moyen-Orient, en Asie et en Amérique latine. Notre réseau de partenaires combine présence locale, ingénierie et studio français. Nous recherchons de nouveaux partenaires dans des régions sélectionnées.",
'Become a partner — apply' => 'Devenir partenaire — postulez',
'Why partner with Asterion' => 'Pourquoi être partenaire d\'Asterion',
'A complete commercial framework.' => 'Un cadre commercial complet.',
'What we look for' => 'Ce que nous recherchons',
'Selection criteria.' => 'Critères de sélection.',
];
}
/* -----------------------------------------------------------------
URL trigger
----------------------------------------------------------------- */
add_action('template_redirect', function () {
if (empty($_GET['av_generate_editorial'])) return;
if (! in_array($_SERVER['SERVER_NAME'] ?? '', ['localhost', '127.0.0.1'], true)) wp_die('localhost only');
$data_file = 'C:\\ASTERION\\GIT\\WP2026\\content-source\\editorial-data.php';
if (! file_exists($data_file)) wp_die("data file not found: $data_file");
$editorial = include $data_file;
if (! is_array($editorial)) wp_die('editorial data not array');
$report = ["Rebuilding editorial pages (top-level, no hub)..."];
// 5 top-level detail pages : why-asterion, about, customers, trust, partners
foreach ($editorial as $slug => $d) {
$page = av_upsert_detail_page($slug, '', $d); // empty parent_path → top-level
$report[] = " $slug → page #{$page['id']} ({$page['action']}) — {$page['element_count']} elements (json={$page['json_len']}, stored={$page['stored_len']})";
}
header('Content-Type: text/plain; charset=utf-8');
echo implode("\n", $report);
exit;
});