The simplest way to add languages to a catalog is to duplicate a page and translate it.
As new works arrive, the harder question becomes how many copies of the data each update must touch. Should a README change require another website edit? Should one unavailable translation break every other language?
For Astra Games, I started with content ownership. The awesome-gpt-6-astra collection maintains the work records. The website reads and presents them without maintaining a second manually edited list in its own code.
One authority can contain multiple files
The upstream repository has a README for each language. A locale registry maps the language code to its file, display label, HTML language value, and reading direction. English reads README.md; Simplified Chinese reads README.zh-CN.md.
Translations still need maintenance. A single source of truth means that work information has one owner, not that all localized content becomes one file.
Navigation, buttons, and status copy live in local dictionaries. Work titles, descriptions, and links come from the corresponding catalog. This lets the site's interface evolve without creating another editorial copy of the works. Locale registry and dictionaries
The parser also has a clear origin. It reuses the upstream website's implementation, adapted for Next.js bundling. Sharing those parsing rules helps prevent the collection and its website from drifting into different interpretations of the same Markdown. Catalog parser
Automatic updates need a freshness contract
Each language has an independent catalog service with its own cache, ETag, and last successful result. Successful reads are reused for five minutes. The next access after expiry triggers a refresh, while concurrent reads within the same process reuse the in-flight request. Catalog service
“Automatic synchronization” therefore means refresh on access with a cache window. It does not mean an upstream commit immediately pushes an update to every open page.
There is another subtle boundary between origin and CDN caching. If a result has already spent four minutes in the server cache, giving it a new five-minute CDN lifetime extends its freshness beyond the intended window. The implementation passes the remaining freshness budget to the CDN instead.
I find it useful to describe caching as a product contract: when readers can expect changes, what they see after a failure, and whether the page identifies that state accurately.
Fallback data has provenance and a lifetime
When upstream is temporarily unavailable, removing the whole catalog is not the only option:
textFresh cache → reuse it Expired cache → request that language's README Success → update catalog and check time Failure → last successful result → bundled snapshot → unavailable
These outcomes should not all be presented as current data. The implementation distinguishes fresh, stale, fallback, and unavailable results, with a shorter retry interval after failure.
Bundled snapshots currently exist only for English and Simplified Chinese. Another language can become unavailable when a cold instance cannot reach upstream. It would be inaccurate to claim that all twelve languages have offline fallback.
The last successful result is also process-local state rather than durable storage shared across instances. After a restart or a new instance, available data depends on upstream access and bundled snapshots. Caching and fallback implementation
Making those limits explicit helps identify when shared caching becomes useful, rather than adding infrastructure before the catalog needs it.
Translation must preserve the identity of the work
A game's translated title can produce a different detail-page slug. Replacing the language segment of a URL therefore does not guarantee that the corresponding page exists.
The current implementation associates translations using the demo URL, then the source or repository URL when needed. It generates language alternates only for entries it actually finds. A missing translation or failed locale load can be omitted without failing the original detail page. Cross-language work matching
This depends on stable links. If a game later uses different demo domains by language, an explicit work ID would be a stronger identity. The existing approach is useful within the shape of today's collection, with that assumption kept visible.
Arabic supplies another reminder that localization includes more than strings. Its locale definition records rtl, which the layout passes to the page's dir attribute. Having a translated dictionary is not enough to establish the correct reading direction.
Supporting twelve languages ultimately tests the same maintenance decisions: where information changes, when cached data refreshes, how failures are represented, and how different pages continue to identify the same work.
Explore the source · Open the catalog
This article describes the implementation inspected on September 11, 2026.
