ニュース / ONI Games

Pythonスクリプト1本で16言語・300ページのゲームサイトを作った方法

CMSもフレームワークも使いません。1つのPythonファイルがonirealms.comの全ページを16言語で書き出し、小さなCloudflare Workerが配信します。

私たちはAndroid向けの無料ゲームを作っています。放置RPGが2本、ブロックパズルが1本、ロボット工場の経営ゲームが1本です。どのゲームにも専用ページが必要で、しかも各ページはゲームが遊ばれているすべての言語で用意しなければなりません。英語、ドイツ語、スペイン語(スペインとラテンアメリカ)、フランス語、クロアチア語、インドネシア語、イタリア語、日本語、韓国語、ポルトガル語(ブラジルとポルトガル)、ロシア語、スロベニア語、トルコ語、繁体字中国語の16種類です。

ゲームが変わるたびに変わるサイトに、CMSは大がかりすぎると感じました。そこでonirealms.com全体を1本のPythonスクリプトが静的ファイルとして書き出し、その前に小さなCloudflare Workerを置いています。

全体の構成

スクリプトsite.pyは約3,200行の1ファイルです。中にはGAMESという辞書があり、ゲームごとにパッケージ名、テーマ、キーアート、セクション間のアート帯、ジャンル、年齢レーティング、公開済みかどうかが入っています。それ以外はすべてここから導き出されます。

テキストは言語ごとに分けた普通のPython辞書に入っていて、トップページ、各ゲーム、FAQ、SEO用のタイトルと説明文、攻略ガイド、ニュースと、領域ごとに1モジュールです。ゲームページは、ゲームと言語を受け取ってHTMLを返す関数です。4本のゲームを16言語で、さらにトップページ、ニュース、ガイド、サイボーグ図鑑、プライバシーポリシー、プレスキットを合わせると300ページを超えます。フルビルドにかかる時間は約26秒です。

日本語、ドイツ語、ロシア語のBlock Brainストア画像。
日本語、ドイツ語、ロシア語のBlock Brainストア画像。

結局、ジェネレーターそのものより大事だったことが3つあります。

1. hreflangは完全でなければ意味がない

各ページは自分自身を含むすべての言語版へのリンクと、x-defaultを持っています。サイトマップも同じグループを繰り返します。1つでも欠けると、検索エンジンはそれらのページを無関係なほぼ重複ページとして扱います。スクリプトはページを書き出すのと同じ言語リストからこのリンクを作るので、両者がずれることはありません。

2. 言語リダイレクトでクローラーを閉じ込めない

Workerは、英語ページに来た訪問者をブラウザの言語の同じページへ送ります。プレイヤーには便利ですが、単純に実装すると検索には致命的です。クローラーにはリダイレクトしか見えなくなるからです。そこでボットはリダイレクトせず、サイト内の別ページから来た訪問者(あえて英語を選んだ人)もリダイレクトせず、アドレスに?lang=があれば無効にし、Cookieも使いません。Vary: Accept-Language付きの302で、301には決してしません。

3. 変更不可のアセットには新しいファイル名を

/assets/以下はすべてCache-Control: max-age=31536000, immutableで配信しています。これは正しい設定ですが、画像を差し替えても1年間誰にも見えないという落とし穴があります。そのため画像生成スクリプトは、古いファイルを上書きせず、新しいバージョンごとに新しいファイル名で書き出します。

4本すべてのストア画像:韓国語のBlock Brain、トルコ語のIdle AI Factory、英語のIdle SummonerとIdle Ronin。
4本すべてのストア画像:韓国語のBlock Brain、トルコ語のIdle AI Factory、英語のIdle SummonerとIdle Ronin。

地味だけど役に立つ仕組み

  • 各ゲームページのQRコードはビルド時に生成します。Worker上の短いリンク/go/<game>を指し、リファラータグ付きでGoogle Playへ転送するので、Play Consoleで流入元ごとのインストール数が見られます。
  • 同意に基づくアナリティクス。タグはすべてのストレージを拒否した状態(consent mode v2)で始まり、訪問者がCookieバナーで同意して初めて有効になります。
  • デプロイのたびにIndexNowを送信し、BingとYandexが当日中に変更を把握できるようにしています。
  • 言語ごとのRSSフィードで、フィードリーダーやアグリゲーターがニュースを拾えます。
  • プレスキットはZIPファイルで、ゲームの画像からスクリプトがまとめています。

やり直すならこうする

言語リストとテキストの表は、HTMLより先に書くこと。英語前提のマークアップに後から16言語を組み込むのが、プロジェクト全体でいちばん時間のかかる作業でした。行の長さ、日本語・韓国語・中国語のフォールバックフォント、ロシア語用のキリル文字フォールバックと、それぞれに個別の対応が必要でした。

ゲームはIdle Ronin: Cyber RPG、Idle Summoner: Pixel RPG、Block Brain、Idle AI Factory: Robot Tycoonの4本で、すべてGoogle Playで無料です。

すべてのニュース

すべてのニュース