UK
games/webrtc-demo / tools / site / build.py · commit 87ad512
#!/usr/bin/env python3"""The web site of the example game in the playground's 14 languages: site/index.html (English) and site/<code>/index.html,sitemap.xml. Run it after tools/site/shots.sh, from anywhere:  python3 games/webrtc-demo/tools/site/build.py"""import html, json, osSITE = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))), 'site')DOCS = 'https://jumphp.net/extensions/jumphp/webrtc/'NAMES = {'en': 'English', 'fr': 'Français', 'es': 'Español', 'de': 'Deutsch', 'it': 'Italiano', 'pt': 'Português', 'nl': 'Nederlands',         'pl': 'Polski', 'ru': 'Русский', 'uk': 'Українська', 'tr': 'Türkçe', 'ja': '日本語', 'zh': '中文', 'ko': '한국어'}LOCALES = {'en': 'en_US', 'fr': 'fr_FR', 'es': 'es_ES', 'de': 'de_DE', 'it': 'it_IT', 'pt': 'pt_PT', 'nl': 'nl_NL', 'pl': 'pl_PL',           'ru': 'ru_RU', 'uk': 'uk_UA', 'tr': 'tr_TR', 'ja': 'ja_JP', 'zh': 'zh_CN', 'ko': 'ko_KR'}# title, description, play, what, li1, li2, li3, controls_h, controls, use_h, use, tutorial, documentation, shots_h, alt, footer, genreT = {'en': ['WebRTC example game – peer to peer in PHP, play free online', 'Two WebRTC peers talking on one screen, then a star-catching duel peer to peer, against a bot or online: the example game of JumPHP\'s WebRTC extension.', '▶ Play', 'What you can try', 'Two peers on this screen: two WebRTC connections inside your page talk through data channels. A PING comes back as a PONG with its round trip, and your cursor travels over an unreliable channel, like UDP.', 'Practice against a bot: a star-catching duel. The bot has its own WebRTC peer and plays through it, like a remote player.', 'Play online: two players meet on the relay, which only passes on their WebRTC signals; then the game goes straight from one browser to the other.', 'Controls', 'Keyboard: arrows, Space, Enter, Escape. Mouse or finger: click the buttons, hold to move. Phone: the on-screen pad works too.', 'Use it in your own game', 'The jumphp/webrtc extension: the same PHP code in the browser (RTCPeerConnection) and on the desktop (GStreamer).', 'tutorial, step by step', 'documentation', 'Screenshots', 'Screenshot of the WebRTC example game', 'Made in PHP with JumPHP.', 'Multiplayer demo'],'fr': ['Jeu d\'exemple WebRTC – du pair à pair en PHP, jouez gratuitement en ligne', 'Deux pairs WebRTC qui se parlent sur un écran, puis un duel d\'étoiles en pair à pair, contre un bot ou en ligne : le jeu d\'exemple de l\'extension WebRTC de JumPHP.', '▶ Jouer', 'Ce que vous pouvez essayer', 'Deux pairs sur cet écran : deux connexions WebRTC dans votre page se parlent par des canaux de données. Un PING revient en PONG avec son temps d\'aller-retour, et votre curseur passe par un canal non fiable, comme en UDP.', 'S\'entraîner contre un bot : un duel pour attraper des étoiles. Le bot a son propre pair WebRTC et joue à travers lui, comme un joueur distant.', 'Jouer en ligne : deux joueurs se retrouvent sur le relais, qui ne fait que transmettre leurs signaux WebRTC ; ensuite le jeu va directement d\'un navigateur à l\'autre.', 'Commandes', 'Clavier : flèches, Espace, Entrée, Échap. Souris ou doigt : cliquez les boutons, maintenez pour bouger. Téléphone : la croix à l\'écran marche aussi.', 'L\'utiliser dans votre jeu', 'L\'extension jumphp/webrtc : le même code PHP dans le navigateur (RTCPeerConnection) et sur l\'ordinateur (GStreamer).', 'tutoriel pas à pas', 'documentation', 'Captures d\'écran', 'Capture du jeu d\'exemple WebRTC', 'Fait en PHP avec JumPHP.', 'Démo multijoueur'],'es': ['Juego de ejemplo WebRTC – de igual a igual en PHP, juega gratis en línea', 'Dos pares WebRTC que hablan en una pantalla y un duelo de estrellas de igual a igual, contra un bot o en línea: el juego de ejemplo de la extensión WebRTC de JumPHP.', '▶ Jugar', 'Qué puedes probar', 'Dos pares en esta pantalla: dos conexiones WebRTC dentro de tu página hablan por canales de datos. Un PING vuelve como PONG con su tiempo de ida y vuelta, y tu cursor viaja por un canal no fiable, como UDP.', 'Practicar contra un bot: un duelo para atrapar estrellas. El bot tiene su propio par WebRTC y juega a través de él, como un jugador remoto.', 'Jugar en línea: dos jugadores se encuentran en el relé, que solo transmite sus señales WebRTC; después el juego va directo de un navegador al otro.', 'Controles', 'Teclado: flechas, Espacio, Intro, Escape. Ratón o dedo: pulsa los botones, mantén para moverte. Móvil: también funciona la cruceta en pantalla.', 'Úsalo en tu propio juego', 'La extensión jumphp/webrtc: el mismo código PHP en el navegador (RTCPeerConnection) y en el ordenador (GStreamer).', 'tutorial paso a paso', 'documentación', 'Capturas', 'Captura del juego de ejemplo WebRTC', 'Hecho en PHP con JumPHP.', 'Demo multijugador'],'de': ['WebRTC-Beispielspiel – Peer-to-Peer in PHP, kostenlos online spielen', 'Zwei WebRTC-Peers, die auf einem Bildschirm sprechen, dann ein Sternenduell Peer-to-Peer, gegen einen Bot oder online: das Beispielspiel der JumPHP-Erweiterung WebRTC.', '▶ Spielen', 'Was du ausprobieren kannst', 'Zwei Peers auf diesem Bildschirm: zwei WebRTC-Verbindungen in deiner Seite sprechen über Datenkanäle. Ein PING kommt als PONG mit seiner Laufzeit zurück, und dein Cursor reist über einen unzuverlässigen Kanal, wie UDP.', 'Gegen einen Bot üben: ein Duell ums Sternefangen. Der Bot hat seinen eigenen WebRTC-Peer und spielt darüber, wie ein entfernter Spieler.', 'Online spielen: zwei Spieler treffen sich auf dem Relay, das nur ihre WebRTC-Signale weitergibt; danach läuft das Spiel direkt von Browser zu Browser.', 'Steuerung', 'Tastatur: Pfeile, Leertaste, Enter, Escape. Maus oder Finger: Knöpfe anklicken, gedrückt halten zum Bewegen. Handy: das Steuerkreuz auf dem Bildschirm geht auch.', 'In deinem eigenen Spiel nutzen', 'Die Erweiterung jumphp/webrtc: derselbe PHP-Code im Browser (RTCPeerConnection) und auf dem Desktop (GStreamer).', 'Tutorial Schritt für Schritt', 'Dokumentation', 'Screenshots', 'Screenshot des WebRTC-Beispielspiels', 'Gemacht in PHP mit JumPHP.', 'Mehrspieler-Demo'],'it': ['Gioco di esempio WebRTC – peer-to-peer in PHP, gioca gratis online', 'Due peer WebRTC che si parlano su uno schermo, poi un duello di stelle peer-to-peer, contro un bot o online: il gioco di esempio dell\'estensione WebRTC di JumPHP.', '▶ Gioca', 'Cosa puoi provare', 'Due peer su questo schermo: due connessioni WebRTC nella tua pagina si parlano tramite canali dati. Un PING torna come PONG con il suo tempo di andata e ritorno, e il tuo cursore viaggia su un canale non affidabile, come UDP.', 'Allenati contro un bot: un duello per prendere le stelle. Il bot ha il suo peer WebRTC e gioca attraverso di esso, come un giocatore remoto.', 'Gioca online: due giocatori si incontrano sul relay, che passa solo i loro segnali WebRTC; poi il gioco va diretto da un browser all\'altro.', 'Comandi', 'Tastiera: frecce, Spazio, Invio, Esc. Mouse o dito: clicca i pulsanti, tieni premuto per muoverti. Telefono: funziona anche la croce a schermo.', 'Usalo nel tuo gioco', 'L\'estensione jumphp/webrtc: lo stesso codice PHP nel browser (RTCPeerConnection) e sul desktop (GStreamer).', 'tutorial passo passo', 'documentazione', 'Schermate', 'Schermata del gioco di esempio WebRTC', 'Fatto in PHP con JumPHP.', 'Demo multigiocatore'],'pt': ['Jogo de exemplo WebRTC – ponto a ponto em PHP, jogue grátis online', 'Dois pares WebRTC que conversam num ecrã e um duelo de estrelas ponto a ponto, contra um bot ou online: o jogo de exemplo da extensão WebRTC do JumPHP.', '▶ Jogar', 'O que pode experimentar', 'Dois pares neste ecrã: duas ligações WebRTC dentro da sua página falam por canais de dados. Um PING volta como PONG com o seu tempo de ida e volta, e o seu cursor viaja por um canal não fiável, como UDP.', 'Treinar contra um bot: um duelo para apanhar estrelas. O bot tem o seu próprio par WebRTC e joga através dele, como um jogador remoto.', 'Jogar online: dois jogadores encontram-se no relé, que só passa os seus sinais WebRTC; depois o jogo vai direto de um navegador ao outro.', 'Controlos', 'Teclado: setas, Espaço, Enter, Escape. Rato ou dedo: clique nos botões, mantenha para mover. Telemóvel: a cruz no ecrã também funciona.', 'Use-o no seu jogo', 'A extensão jumphp/webrtc: o mesmo código PHP no navegador (RTCPeerConnection) e no computador (GStreamer).', 'tutorial passo a passo', 'documentação', 'Capturas de ecrã', 'Captura do jogo de exemplo WebRTC', 'Feito em PHP com JumPHP.', 'Demo multijogador'],'nl': ['WebRTC-voorbeeldspel – peer-to-peer in PHP, gratis online spelen', 'Twee WebRTC-peers die op één scherm praten, daarna een sterrenduel peer-to-peer, tegen een bot of online: het voorbeeldspel van de JumPHP-extensie WebRTC.', '▶ Spelen', 'Wat je kunt proberen', 'Twee peers op dit scherm: twee WebRTC-verbindingen in je pagina praten via datakanalen. Een PING komt terug als PONG met de rondetijd, en je cursor reist over een onbetrouwbaar kanaal, zoals UDP.', 'Oefenen tegen een bot: een duel om sterren te vangen. De bot heeft een eigen WebRTC-peer en speelt daarlangs, als een speler op afstand.', 'Online spelen: twee spelers ontmoeten elkaar op de relay, die alleen hun WebRTC-signalen doorgeeft; daarna gaat het spel rechtstreeks van browser naar browser.', 'Besturing', 'Toetsenbord: pijlen, Spatie, Enter, Escape. Muis of vinger: klik op de knoppen, houd vast om te bewegen. Telefoon: het pad op het scherm werkt ook.', 'Gebruik het in je eigen spel', 'De extensie jumphp/webrtc: dezelfde PHP-code in de browser (RTCPeerConnection) en op de desktop (GStreamer).', 'tutorial stap voor stap', 'documentatie', 'Schermafbeeldingen', 'Schermafbeelding van het WebRTC-voorbeeldspel', 'Gemaakt in PHP met JumPHP.', 'Multiplayerdemo'],'pl': ['Przykładowa gra WebRTC – peer-to-peer w PHP, graj za darmo online', 'Dwa węzły WebRTC rozmawiające na jednym ekranie, potem pojedynek o gwiazdki peer-to-peer, z botem lub online: przykładowa gra rozszerzenia WebRTC dla JumPHP.', '▶ Graj', 'Co możesz wypróbować', 'Dwa węzły na tym ekranie: dwa połączenia WebRTC na twojej stronie rozmawiają kanałami danych. PING wraca jako PONG z czasem w obie strony, a twój kursor podróżuje zawodnym kanałem, jak UDP.', 'Trening z botem: pojedynek o łapanie gwiazdek. Bot ma własny węzeł WebRTC i gra przez niego, jak zdalny gracz.', 'Gra online: dwóch graczy spotyka się na przekaźniku, który przekazuje tylko ich sygnały WebRTC; potem gra idzie prosto z przeglądarki do przeglądarki.', 'Sterowanie', 'Klawiatura: strzałki, Spacja, Enter, Escape. Mysz lub palec: klikaj przyciski, przytrzymaj, by się ruszać. Telefon: działa też krzyżak na ekranie.', 'Użyj go we własnej grze', 'Rozszerzenie jumphp/webrtc: ten sam kod PHP w przeglądarce (RTCPeerConnection) i na komputerze (GStreamer).', 'samouczek krok po kroku', 'dokumentacja', 'Zrzuty ekranu', 'Zrzut ekranu przykładowej gry WebRTC', 'Zrobione w PHP z JumPHP.', 'Demo wieloosobowe'],'ru': ['Пример игры WebRTC – peer-to-peer на PHP, играйте бесплатно онлайн', 'Два WebRTC-пира общаются на одном экране, затем дуэль за звёзды напрямую, против бота или онлайн: пример игры для расширения WebRTC JumPHP.', '▶ Играть', 'Что можно попробовать', 'Два пира на этом экране: два WebRTC-соединения в вашей странице общаются по каналам данных. PING возвращается как PONG со временем туда и обратно, а ваш курсор идёт по ненадёжному каналу, как UDP.', 'Тренировка с ботом: дуэль на ловлю звёзд. У бота свой WebRTC-пир, и он играет через него, как удалённый игрок.', 'Игра онлайн: два игрока встречаются на ретрансляторе, который лишь передаёт их WebRTC-сигналы; дальше игра идёт напрямую из браузера в браузер.', 'Управление', 'Клавиатура: стрелки, Пробел, Enter, Escape. Мышь или палец: нажимайте кнопки, удерживайте, чтобы двигаться. Телефон: экранный джойстик тоже работает.', 'Используйте в своей игре', 'Расширение jumphp/webrtc: один и тот же PHP-код в браузере (RTCPeerConnection) и на компьютере (GStreamer).', 'пошаговое руководство', 'документация', 'Скриншоты', 'Скриншот примера игры WebRTC', 'Сделано на PHP с JumPHP.', 'Мультиплеерное демо'],'uk': ['Приклад гри WebRTC – peer-to-peer на PHP, грайте безкоштовно онлайн', 'Два WebRTC-піри спілкуються на одному екрані, потім дуель за зірки напряму, проти бота або онлайн: приклад гри для розширення WebRTC JumPHP.', '▶ Грати', 'Що можна спробувати', 'Два піри на цьому екрані: два WebRTC-з’єднання у вашій сторінці спілкуються каналами даних. PING повертається як PONG із часом туди й назад, а ваш курсор іде ненадійним каналом, як UDP.', 'Тренування з ботом: дуель на ловлю зірок. Бот має власний WebRTC-пір і грає через нього, як віддалений гравець.', 'Гра онлайн: два гравці зустрічаються на ретрансляторі, який лише передає їхні WebRTC-сигнали; далі гра йде напряму з браузера в браузер.', 'Керування', 'Клавіатура: стрілки, Пробіл, Enter, Escape. Миша або палець: натискайте кнопки, утримуйте, щоб рухатися. Телефон: екранний джойстик теж працює.', 'Використайте у своїй грі', 'Розширення jumphp/webrtc: той самий PHP-код у браузері (RTCPeerConnection) і на комп’ютері (GStreamer).', 'покроковий посібник', 'документація', 'Знімки екрана', 'Знімок екрана прикладу гри WebRTC', 'Зроблено на PHP з JumPHP.', 'Багатокористувацьке демо'],'tr': ['WebRTC örnek oyunu – PHP ile eşler arası, çevrim içi ücretsiz oyna', 'Tek ekranda konuşan iki WebRTC eşi, ardından bota karşı ya da çevrim içi eşler arası bir yıldız düellosu: JumPHP WebRTC eklentisinin örnek oyunu.', '▶ Oyna', 'Neler deneyebilirsiniz', 'Bu ekranda iki eş: sayfanızdaki iki WebRTC bağlantısı veri kanallarıyla konuşur. Bir PING, gidiş-dönüş süresiyle PONG olarak döner; imleciniz UDP gibi güvenilmez bir kanaldan gider.', 'Bota karşı alıştırma: yıldız toplama düellosu. Botun kendi WebRTC eşi vardır ve uzaktaki bir oyuncu gibi onun üzerinden oynar.', 'Çevrim içi oyna: iki oyuncu yalnızca WebRTC sinyallerini ileten röle üzerinde buluşur; sonra oyun doğrudan bir tarayıcıdan ötekine gider.', 'Kontroller', 'Klavye: oklar, Boşluk, Enter, Escape. Fare ya da parmak: düğmelere tıklayın, hareket için basılı tutun. Telefon: ekrandaki yön tuşları da çalışır.', 'Kendi oyununuzda kullanın', 'jumphp/webrtc eklentisi: tarayıcıda (RTCPeerConnection) ve masaüstünde (GStreamer) aynı PHP kodu.', 'adım adım eğitim', 'belgeler', 'Ekran görüntüleri', 'WebRTC örnek oyununun ekran görüntüsü', 'JumPHP ile PHP\'de yapıldı.', 'Çok oyunculu demo'],'ja': ['WebRTC サンプルゲーム – PHP で P2P、無料でオンラインプレイ', '1 つの画面で通信する 2 つの WebRTC ピア、そしてボットやオンラインの相手と P2P で星を集める対戦。JumPHP の拡張機能 WebRTC のサンプルゲームです。', '▶ プレイ', '試せること', 'この画面に 2 つのピア: ページ内の 2 つの WebRTC 接続がデータチャネルで通信します。PING は往復時間つきの PONG として返り、カーソルは UDP のような信頼性のないチャネルで送られます。', 'ボットと練習: 星を集める対戦。ボットは自分の WebRTC ピアを持ち、離れたプレイヤーのようにそれを通して遊びます。', 'オンラインで遊ぶ: 2 人はリレーで出会い、リレーは WebRTC のシグナルを渡すだけ。その後ゲームはブラウザからブラウザへ直接つながります。', '操作', 'キーボード: 矢印、スペース、Enter、Esc。マウスや指: ボタンをクリック、押したままで移動。スマホ: 画面上のパッドも使えます。', '自分のゲームで使う', '拡張機能 jumphp/webrtc: ブラウザ (RTCPeerConnection) でもデスクトップ (GStreamer) でも同じ PHP コード。', 'ステップごとのチュートリアル', 'ドキュメント', 'スクリーンショット', 'WebRTC サンプルゲームのスクリーンショット', 'JumPHP を使って PHP で作られました。', 'マルチプレイのデモ'],'zh': ['WebRTC 示例游戏 – 用 PHP 实现点对点,免费在线玩', '两个 WebRTC 对等端在同一屏幕上通信,再来一场点对点的摘星对决,对手可以是机器人或在线玩家:JumPHP 扩展 WebRTC 的示例游戏。', '▶ 开始', '可以试试', '同一屏幕上的两个对等端:页面里的两个 WebRTC 连接通过数据通道通信。PING 会带着往返时间以 PONG 返回,光标则像 UDP 一样走不可靠通道。', '与机器人练习:一场摘星星对决。机器人有自己的 WebRTC 对等端,像远程玩家一样通过它来玩。', '在线游戏:两名玩家在中继服务器上相遇,中继只传递他们的 WebRTC 信令;之后游戏直接在两个浏览器之间进行。', '操作', '键盘:方向键、空格、回车、Esc。鼠标或手指:点击按钮,按住移动。手机:屏幕上的方向键也能用。', '在你自己的游戏里使用', '扩展 jumphp/webrtc:浏览器 (RTCPeerConnection) 与桌面 (GStreamer) 上是同一份 PHP 代码。', '分步教程', '文档', '截图', 'WebRTC 示例游戏截图', '使用 JumPHP 以 PHP 制作。', '多人演示'],'ko': ['WebRTC 예제 게임 – PHP로 P2P, 무료 온라인 플레이', '한 화면에서 대화하는 두 WebRTC 피어, 그리고 봇이나 온라인 상대와 P2P로 별을 모으는 대결: JumPHP 확장 WebRTC의 예제 게임입니다.', '▶ 플레이', '해 볼 수 있는 것', '이 화면의 두 피어: 페이지 안의 두 WebRTC 연결이 데이터 채널로 대화합니다. PING은 왕복 시간과 함께 PONG으로 돌아오고, 커서는 UDP처럼 신뢰성 없는 채널로 전달됩니다.', '봇과 연습: 별을 모으는 대결. 봇은 자기 WebRTC 피어를 갖고, 원격 플레이어처럼 그것을 통해 플레이합니다.', '온라인 플레이: 두 플레이어는 WebRTC 신호만 전달하는 릴레이에서 만나고, 그다음 게임은 브라우저에서 브라우저로 바로 연결됩니다.', '조작', '키보드: 화살표, 스페이스, Enter, Esc. 마우스나 손가락: 버튼을 누르고, 누른 채로 이동. 휴대폰: 화면의 패드도 됩니다.', '내 게임에서 사용하기', '확장 jumphp/webrtc: 브라우저(RTCPeerConnection)와 데스크톱(GStreamer)에서 같은 PHP 코드.', '단계별 튜토리얼', '문서', '스크린샷', 'WebRTC 예제 게임 스크린샷', 'JumPHP로 PHP에서 만들었습니다.', '멀티플레이 데모'],}def page(lang):    t = T[lang]    e = html.escape    up = '' if lang == 'en' else '../'    url = 'https://{{DOMAIN}}/' + ('' if lang == 'en' else lang + '/')    alts = '\n'.join(f'  <link rel="alternate" hreflang="{c}" href="https://{{{{DOMAIN}}}}/{"" if c == "en" else c + "/"}">' for c in T)    alts += '\n  <link rel="alternate" hreflang="x-default" href="https://{{DOMAIN}}/">'    menu = ' · '.join(f'<a href="{up}{"" if c == "en" else c + "/"}" lang="{c}"{" aria-current=\"page\"" if c == lang else ""}>{NAMES[c]}</a>' for c in T)    play = up + 'play/' + ('' if lang == 'en' else f'?lang={lang}&back=../{lang}/')    ld = {'@context': 'https://schema.org', '@type': 'VideoGame', 'name': 'WebRTC – JumPHP', 'description': t[1], 'url': url,          'genre': t[16], 'gamePlatform': ['Web browser', 'PC', 'Mobile'], 'applicationCategory': 'Game', 'operatingSystem': 'Any',          'image': 'https://{{DOMAIN}}/images/og.png', 'screenshot': [f'https://{{{{DOMAIN}}}}/images/shot-{i}.png' for i in range(1, 5)],          'isAccessibleForFree': True, 'inLanguage': lang, 'numberOfPlayers': {'@type': 'QuantitativeValue', 'minValue': 1, 'maxValue': 2},          'potentialAction': {'@type': 'PlayAction', 'target': 'https://{{DOMAIN}}/play/'}}    shots = '\n'.join(f'      <img src="{up}images/shot-{i}.png" alt="{e(t[14])} {i}" width="640" height="360" loading="lazy">' for i in range(1, 5))    return f'''<!doctype html><html lang="{lang}"><head>  <meta charset="utf-8">  <meta name="viewport" content="width=device-width, initial-scale=1">  <title>{e(t[0])}</title>  <meta name="description" content="{e(t[1])}">  <link rel="canonical" href="{url}">{alts}  <link rel="icon" href="{up}images/favicon.png">  <meta property="og:type" content="website">  <meta property="og:title" content="{e(t[0])}">  <meta property="og:description" content="{e(t[1])}">  <meta property="og:url" content="{url}">  <meta property="og:image" content="https://{{{{DOMAIN}}}}/images/og.png">  <meta property="og:locale" content="{LOCALES[lang]}">  <meta name="twitter:card" content="summary_large_image">  <meta name="twitter:title" content="{e(t[0])}">  <meta name="twitter:description" content="{e(t[1])}">  <meta name="twitter:image" content="https://{{{{DOMAIN}}}}/images/og.png">  <script type="application/ld+json">{json.dumps(ld, ensure_ascii=False, indent=2)}  </script>  <style>    :root {{ --bg: #0a0c18; --panel: #161a30; --text: #eef0ff; --muted: #a7acc9; --me: #40d680; --other: #ff9640; --accent: #5ac8ff; }}    * {{ box-sizing: border-box; }}    body {{ margin: 0; background: var(--bg); color: var(--text); font: 17px/1.6 system-ui, -apple-system, "Segoe UI", sans-serif; }}    main {{ max-width: 1000px; margin: 0 auto; padding: 16px 16px 64px; }}    nav {{ font-size: 13px; color: var(--muted); text-align: center; line-height: 2; }}    nav a {{ color: var(--muted); text-decoration: none; white-space: nowrap; }}    nav a[aria-current] {{ color: var(--text); font-weight: 700; }}    header {{ text-align: center; padding: 24px 0 8px; }}    .peers {{ display: flex; align-items: center; justify-content: center; gap: 12px; margin-bottom: 8px; }}    .peers i {{ width: 28px; height: 28px; display: block; }}    .peers b {{ flex: 0 1 220px; height: 2px; background: linear-gradient(90deg, var(--me), var(--other)); }}    h1 {{ font-size: clamp(32px, 7vw, 56px); margin: 0 0 8px; letter-spacing: 1px; }}    h2 {{ margin: 48px 0 12px; font-size: 24px; }}    p, li {{ color: var(--muted); }}    li {{ margin-bottom: 8px; }}    li strong {{ color: var(--text); }}    .play {{ display: inline-block; margin: 20px 0; padding: 16px 40px; border-radius: 12px; background: var(--me); color: #07130c;      font-weight: 800; font-size: 22px; text-decoration: none; box-shadow: 0 6px 0 #1f8a4c; }}    .play:active {{ transform: translateY(4px); box-shadow: 0 2px 0 #1f8a4c; }}    .hero img, .gallery img {{ width: 100%; height: auto; image-rendering: pixelated; border-radius: 10px; display: block; background: #000; }}    .gallery {{ display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: 16px; }}    code {{ background: var(--panel); padding: 2px 6px; border-radius: 6px; color: var(--text); word-break: break-all; }}    footer {{ text-align: center; color: var(--muted); font-size: 14px; margin-top: 56px; }}    a {{ color: var(--accent); }}  </style></head><body>  <main>    <nav aria-label="Language">{menu}</nav>    <header>      <div class="peers" aria-hidden="true"><i style="background: var(--me)"></i><b></b><i style="background: var(--other)"></i></div>      <h1>WebRTC</h1>      <p>{e(t[1])}</p>      <a class="play" href="{play}">{e(t[2])}</a>    </header>    <div class="hero"><img src="{up}images/shot-3.png" alt="{e(t[14])}" width="640" height="360"></div>    <section>      <h2>{e(t[3])}</h2>      <ul>        <li>{e(t[4])}</li>        <li>{e(t[5])}</li>        <li>{e(t[6])}</li>      </ul>    </section>    <section>      <h2>{e(t[7])}</h2>      <p>{e(t[8])}</p>    </section>    <section>      <h2>{e(t[9])}</h2>      <p>{e(t[10])}</p>      <p><a href="{DOCS}tutoriel">{e(t[11])}</a> · <a href="{DOCS}documentation">{e(t[12])}</a> · <code>bin/jumphp extension:add &lt;game&gt; jumphp/webrtc</code></p>    </section>    <section>      <h2>{e(t[13])}</h2>      <div class="gallery">{shots}      </div>    </section>    <p style="text-align: center"><a class="play" href="{play}">{e(t[2])}</a></p>    <footer>{e(t[15])}</footer>  </main></body></html>'''for lang in T:    assert len(T[lang]) == 17, lang    d = SITE if lang == 'en' else os.path.join(SITE, lang)    os.makedirs(d, exist_ok=True)    open(os.path.join(d, 'index.html'), 'w', encoding='utf-8').write(page(lang))links = ''.join(f'\n    <xhtml:link rel="alternate" hreflang="{c}" href="https://{{{{DOMAIN}}}}/{"" if c == "en" else c + "/"}"/>' for c in T)urls = ''.join(f'\n  <url>\n    <loc>https://{{{{DOMAIN}}}}/{"" if c == "en" else c + "/"}</loc>{links}\n  </url>' for c in T)open(os.path.join(SITE, 'sitemap.xml'), 'w').write('<?xml version="1.0" encoding="UTF-8"?>\n<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" '                                                   'xmlns:xhtml="http://www.w3.org/1999/xhtml">' + urls + '\n</urlset>\n')print('site written:', len(T), 'languages')