
Aktualności / ONI Games
Jak zbudowaliśmy stronę o grach z 300 podstronami w 16 językach jednym skryptem w Pythonie
Bez CMS i bez frameworka: jeden plik w Pythonie pisze każdą stronę onirealms.com w 16 językach, a mały Cloudflare Worker je serwuje.
Tworzymy darmowe gry na Androida: dwa idle RPG, grę z blokami i tycoon z fabryką robotów. Każda z nich potrzebowała własnej strony, a każda strona musiała istnieć w każdym języku, w którym gra się w nasze gry. To 16 wersji językowych: angielska, niemiecka, hiszpańska (dla Hiszpanii i Ameryki Łacińskiej), francuska, chorwacka, indonezyjska, włoska, japońska, koreańska, portugalska (dla Brazylii i Portugalii), rosyjska, słoweńska, turecka i chińska tradycyjna.
CMS wydawał się zbyt ciężką maszynerią dla strony, która zmienia się wtedy, gdy zmienia się gra. Dlatego całe onirealms.com pisze jeden skrypt w Pythonie jako zwykłe pliki statyczne, a przed nimi stoi mały Cloudflare Worker.
Jak to jest zbudowane
Skrypt site.py to jeden plik liczący około 3200 wierszy. Zawiera słownik GAMES z jednym wpisem na grę: nazwa pakietu, motyw, grafika główna, pasy grafik między sekcjami, gatunki, klasyfikacje wiekowe i to, czy gra jest już dostępna. Wszystko inne wynika z tego.
Teksty żyją w zwykłych słownikach Pythona z kluczami według języka, po jednym module na obszar: strona główna, każda gra, FAQ, tytuły i opisy SEO, poradniki i aktualności. Strona gry to funkcja, która przyjmuje grę i język i zwraca HTML. Cztery gry w 16 językach plus strona główna, aktualności, poradniki, lista cyborgów, polityka prywatności i materiały prasowe dają razem ponad 300 stron. Pełne zbudowanie strony trwa około 26 sekund.

Trzy rzeczy okazały się ważniejsze niż sam generator.
1. hreflang musi być kompletny, inaczej nic nie daje
Każda strona linkuje do wszystkich swoich wersji językowych, łącznie z sobą samą, plus x-default. Mapa witryny powtarza te same grupy. Pomiń jedną, a wyszukiwarki uznają strony za niepowiązane, prawie identyczne kopie. Skrypt buduje te linki z tej samej listy języków, której używa do pisania stron, więc obie nie mogą się rozjechać.
2. Przekierowania językowe nie mogą łapać robotów w pułapkę
Worker odsyła osobę, która trafia na angielską stronę, do tej samej strony w języku przeglądarki. To dobre dla graczy i fatalne dla wyszukiwarek, jeśli zrobić to naiwnie, bo robot widziałby tylko przekierowanie. Dlatego przekierowania nie ma dla botów, nie ma go, gdy odwiedzający przyszedł z innej strony witryny (czyli celowo wybrał angielski), nie ma go, gdy adres zawiera ?lang=, i nie ustawia ono żadnego pliku cookie. To 302 z Vary: Accept-Language, nigdy 301.
3. Niezmienne zasoby potrzebują nowych nazw plików
Wszystko pod /assets/ jest serwowane z Cache-Control: max-age=31536000, immutable. To dobre ustawienie, dopóki nie zmienisz obrazka i nikt nie zobaczy zmiany przez rok. Skrypty od grafik zapisują każdą nową wersję pod nową nazwą pliku, zamiast nadpisywać starą.

Małe elementy, które się opłacają
- Kody QR na każdej stronie gry, generowane podczas budowania. Prowadzą do krótkiego linku
/go/<game>w Workerze, który przekazuje do Google Play ze znacznikiem źródła, więc Play Console pokazuje instalacje według źródła. - Analityka z poszanowaniem zgody. Tag startuje z odmową każdego rodzaju przechowywania (consent mode v2) i włącza się dopiero, gdy odwiedzający zaakceptuje baner cookie.
- IndexNow po każdym wdrożeniu, żeby Bing i Yandex widziały zmiany tego samego dnia.
- Kanał RSS dla każdego języka, żeby czytniki kanałów i agregatory zbierały aktualności.
- Materiały prasowe jako pliki ZIP, pakowane skryptem z grafik gier.
Co zrobilibyśmy inaczej
Listę języków i tabele tekstów napisalibyśmy przed HTML, nie po nim. Wciskanie 16 języków w kod, który zakładał angielski, było najwolniejszą częścią całego projektu: długość wierszy, czcionki zapasowe dla japońskiego, koreańskiego i chińskiego oraz zapasowa czcionka cyrylicy dla rosyjskiego wymagały osobnego przejścia.
Te gry to Idle Ronin: Cyber RPG, Idle Summoner: Pixel RPG, Block Brain i Idle AI Factory: Robot Tycoon, wszystkie za darmo w Google Play.







