Actus / ONI Games

Comment nous avons construit un site de 300 pages en 16 langues avec un seul script Python

Ni CMS ni framework : un fichier Python écrit chaque page d’onirealms.com en 16 langues, et un petit Cloudflare Worker les sert.

Nous créons des jeux gratuits pour Android : deux RPG idle, un puzzle de blocs et un tycoon d’usine de robots. Chacun avait besoin de sa propre page, et chaque page devait exister dans toutes les langues où l’on joue à nos jeux. Cela fait 16 versions : anglais, allemand, espagnol (Espagne et Amérique latine), français, croate, indonésien, italien, japonais, coréen, portugais (Brésil et Portugal), russe, slovène, turc et chinois traditionnel.

Un CMS nous semblait trop lourd pour un site qui change quand un jeu change. Tout onirealms.com est donc écrit par un seul script Python sous forme de fichiers statiques, avec un petit Cloudflare Worker devant.

Comment c’est construit

Le script, site.py, est un seul fichier d’environ 3 200 lignes. Il contient un dictionnaire GAMES avec une entrée par jeu : nom de paquet, thème, visuel principal, bandeaux d’illustration entre les sections, genres, classifications d’âge et si le jeu est déjà publié. Tout le reste en découle.

Les textes vivent dans de simples dictionnaires Python, classés par langue, un module par partie : l’accueil, chaque jeu, les FAQ, les titres et descriptions SEO, les guides et les actualités. Une page de jeu est une fonction qui reçoit un jeu et une langue et renvoie du HTML. Quatre jeux en 16 langues, plus l’accueil, les actualités, les guides, un répertoire de cyborgs, la politique de confidentialité et le kit presse : plus de 300 pages. Une génération complète prend environ 26 secondes.

Les visuels de boutique de Block Brain en japonais, allemand et russe.
Les visuels de boutique de Block Brain en japonais, allemand et russe.

Au final, trois choses ont compté davantage que le générateur lui-même.

1. hreflang doit être complet, sinon il ne sert à rien

Chaque page renvoie vers toutes ses autres versions linguistiques, y compris elle-même, plus un x-default. Le sitemap répète les mêmes groupes. S’il en manque un, les moteurs de recherche traitent les pages comme des quasi-doublons sans lien. Le script construit ces liens à partir de la même liste de langues que celle qui sert à écrire les pages, ils ne peuvent donc pas diverger.

2. Les redirections de langue ne doivent pas piéger les robots

Le Worker envoie le visiteur qui arrive sur une page anglaise vers la même page dans la langue de son navigateur. C’est bien pour les joueurs et désastreux pour le référencement si on le fait naïvement, car un robot d’indexation ne verrait jamais que la redirection. La redirection est donc désactivée pour les robots, quand le visiteur vient d’une autre page du site (il a choisi l’anglais exprès), quand l’adresse contient ?lang=, et elle n’utilise aucun cookie. C’est un 302 avec Vary: Accept-Language, jamais un 301.

3. Les ressources immuables ont besoin de nouveaux noms

Tout ce qui se trouve sous /assets/ est servi avec Cache-Control: max-age=31536000, immutable. C’est le bon réglage, jusqu’au jour où l’on modifie une image et que personne ne la voit pendant un an. Les scripts graphiques écrivent donc un nouveau nom de fichier pour chaque nouvelle version au lieu d’écraser l’ancien.

Les visuels de boutique des quatre jeux : Block Brain en coréen, Idle AI Factory en turc, Idle Summoner et Idle Ronin en anglais.
Les visuels de boutique des quatre jeux : Block Brain en coréen, Idle AI Factory en turc, Idle Summoner et Idle Ronin en anglais.

Les petits plus qui valent le coup

  • Des QR codes sur chaque page de jeu, générés pendant le build. Ils pointent vers un lien court /go/<game> du Worker, qui redirige vers Google Play avec une balise de provenance, pour que la Play Console affiche les installations par source.
  • Des statistiques respectueuses du consentement. La balise démarre avec tous les stockages refusés (consent mode v2) et ne s’active qu’après l’accord du visiteur dans la bannière cookies.
  • IndexNow après chaque déploiement, pour que Bing et Yandex voient les changements le jour même.
  • Un flux RSS par langue, pour que les lecteurs de flux et les agrégateurs récupèrent les actualités.
  • Des kits presse en fichiers ZIP, préparés par un script à partir des visuels des jeux.

Ce que nous ferions autrement

Écrire la liste des langues et les tables de textes avant le HTML, pas après. Adapter 16 langues à un balisage pensé pour l’anglais a été la partie la plus lente du projet : longueur des lignes, polices de secours pour le japonais, le coréen et le chinois, et une police cyrillique de secours pour le russe ont chacune demandé leur propre passe.

Les jeux : Idle Ronin: Cyber RPG, Idle Summoner: Pixel RPG, Block Brain et Idle AI Factory: Robot Tycoon, tous gratuits sur Google Play.

Toutes les actus

Toutes les actus