The site speaks Icelandic now
Adding a second language to a website is a morning's work. Adding one a search engine can actually find is a different job — and getting it wrong fails silently, which is the worst way for anything to fail.
Alftanet is now bilingual: English at /, Icelandic at /is/. The
obvious way to build that is a language toggle — a button that swaps the text in place with
JavaScript. It's less code, it's a nicer transition, and it would have been a mistake.
Why a toggle is the wrong tool
A client-side toggle means the site has exactly one address. Whatever language a visitor
picks, they're at alftanet.com/, and so is everyone else.
Which means a search engine has one URL to index, in whichever language the page ships in by default. The Icelandic version isn't hidden, exactly — it's simply never a destination. Nobody searching in Icelandic can be sent to it, because there's no address to send them to. You've translated the site for people who already found it, which is the group that needed it least.
So /is/ is a real, separate, server-rendered page with its own
<title>, its own meta description, its own canonical link and
<html lang="is">. The switcher in the header is two ordinary links. Boring,
and correct.
Telling Google the two pages aren't duplicates
Two pages with the same content in different languages look, to a crawler, uncomfortably like duplicate content — two URLs competing for the same thing, with the search engine choosing one and ignoring the other.
The fix is hreflang, which declares "these are the same page in different
languages, here is the full set". The detail that trips people up is that the declaration has
to be symmetrical: both pages must list all the alternates, including
themselves. A one-way declaration is ignored.
So both pages carry an identical block naming the English URL, the Icelandic URL, and an
x-default for anyone who matches neither. The only thing that differs between the
two pages is the canonical link, which points at itself. The same alternates are repeated in
the sitemap.
How the translation actually works
The English homepage is the single source of truth. The Icelandic page is produced from it at
request time by applying a list of [english, icelandic] string pairs.
There's one trick that makes this survive contact with reality. HTML gets re-wrapped and re-indented constantly, so a translation key written across three lines will stop matching the moment someone reformats the file. Every run of whitespace in a key is therefore compiled into a pattern that matches any run of whitespace in the page — so keys are written on one line here and keep matching however the markup happens to be laid out.
The silent failure, and the warning we built for it
Here's the part that actually worried us. If a translation key stops matching — because a game card was reworded, a typo was fixed, a sentence was tightened — nothing breaks. No error, no missing text, no blank space. The Icelandic page simply keeps showing the old English for that fragment.
That's the worst possible failure mode: invisible to us, because we don't read the Icelandic page every day, and invisible to visitors, who just see a site that's oddly half-translated and assume that's how it is.
So the server checks every key against the page at startup and logs the ones that no longer match:
[i18n:is] string #23 no longer matches index.html
That one line is the entire safety net, and it exists because the alternative is finding out months later. Any time we reword a game card, that warning is how we learn the Icelandic version silently kept the old copy.
If we were doing it again we'd go further and fail the deploy rather than log a warning — a warning still relies on somebody reading the logs. That's a change we'll probably make.
News, and translating things that don't exist yet
The news entries on the front page are a different problem, because they're written after the code ships — they come from an admin tool, not the repository.
Those are translated by entry id, with a deliberate fallback: an entry with no Icelandic version yet renders in English rather than disappearing. A visitor to the Icelandic site sees a new post the moment it's published, in English, and it becomes Icelandic when someone gets to it. The alternative — hiding untranslated posts — means the Icelandic site quietly looks abandoned.
What isn't translated
The games themselves are English-only, and the guides are too. /is/ is the hub
in Icelandic, not a full translation of every page on the site.
That's a real gap rather than a decision we're proud of: an Icelandic visitor is one click from falling back into English. Bringing the top-level pages across is on the list, and the drift-warning mechanism above is what makes that expansion safe to attempt.