Localisation from English to German, how difficult can it be? Spinning up a proof of concept with Contentful and Claude.
In the 1980s, an advertising slogan for a German carmaker became an everyday catchphrase in the UK. Vorsprung durch Technik. The fact that it was never translated or localised didn't matter, it carried a certain resonance for anyone who heard it.
That same slogan has been rattling around in my brain for the duration of this little project, which is to add a basic form of translated content to the site. I think, nominally, it's because the source content is UK English and the target language is German. But also because it's technology that makes a formerly complex process into something more approachable.
Anyway, the upshot is that a select group of posts on this blog have a short line in crimson directly under the byline. It says "Auch auf Deutsch lesen". Click on it and you land on the same essay in German, with the same cover and the same author. And a few refinements that elevate it from basic translation to actual localisation.
Why German? Because I live in Munich, Germany, but I was born and raised in the UK. My first language is English, while learning the German language has been an ongoing (but always delightful) process. The needle moving from one to the other is something I'd like reflected on Be Useful.
Choosing the approach
There are two ways to add a second (or third, or fourth) language to a website. You can dive in headlong and translate the whole site, which means every bit of chrome – the menu, the buttons, dates, tags, everything – then diligently keep all of it in step forever. This requires you to have a defined strategy up front and plan for every contingency.
Or you can slice the elephant and throw together a small proof of concept first. Translate only the most essential parts to make a single post legible to your reader, and then worry about the rest later.
I went for the second. While English is the default option, individual posts can have a second version added to them in German. There's no menu switcher to magically flip from EN to DE and vice versa, and no plugins to translate content on the fly.
Translated pages live under /de/, and otherwise share the English post's address, so the German version of the RetroPie tutorial sits at /de/posts/retropie-raspberry-pi-5. Google's guide to multilingual and multi-regional sites (opens in a new window) lists a folder like this as easy to set up and low maintenance. Translating the address itself is allowed too, but every post would then need a second address kept in step with the first.
Everything around the article stays in English for now. The menu, the footer, the tag pills, the author bios and the related posts at the bottom of the page are all the English site's. A German page is a German article sitting inside an English blog.
Again, this is a proof of concept to see if it works (it does). If I decide down the line that the entire site would benefit from a full localisation plan, e.g., if there's more traffic from an audience in Germany, then that's the path we can take.
How the CMS side works
The posts on this blog live in Contentful, a headless CMS. "Headless" means it stores and serves the content but is completely agnostic about how the website looks. The site asks for a post and gets back individual fields as data.
Languages in the CMS are called locales, and each is usually tied to a region, such as British English (en-GB) or German as written in Germany (de-DE). Each field can hold one value per locale, so a post's title can be "Building blocks for building blogs" in en-GB and „Bausteine für den Blogbau“ in de-DE at the same time.
Only four fields in the content model for this blog hold a German value. They're the post title, the excerpt and the body, which all live on one content type, and the text of a sidenote, which lives on another.
Everything else, from the cover image and the date to the tags, category and authors, is shared between the two versions, apart from an image's alt text and caption, which can carry German of their own. A translation never has to repeat work that has nothing to do with language.

Funny story: the first German page I tested in preview had an empty space where the cover image should have been, and blank circles where the author portraits would go. Asking the CMS for a post in German also asked for its images in German. Every image has a slot for each language, and the German ones were empty, so the page had nothing to show.
The fix was to make two requests instead of one: the German text on its own, and everything else from the English post, stitched together before the page is built.
Overall, though, I'm enjoying how the process is handled within Contentful. You activate the locale when you need it, tidy it away when you don't. And there's a colour-coded tab against each entry to denote whether additional locales are active.
Translating the posts
The German itself comes from Claude. Via the MCP connector, it can read the source copy in English and then write the equivalent German entry into the locale field as an unpublished draft. Human-in-the-loop processes apply just as with any other piece of content: I read it, revise anything that looks wrong, and publish it myself.
(And as an aside, reading back my scribblings in technically perfect German will never not feel uncanny. Several of my language teachers would admonish me for not attempting it myself in the first place.)
A few house rules keep the translations consistent. The German addresses the reader as „du“, the informal you, because the English is informal too. Local considerations also apply: for example, when writing about movies, films keep their official German release titles, so The Wages of Fear becomes „Lohn der Angst“ and Roman Holiday becomes „Ein Herz und eine Krone“.
Asides that only make sense to an English reader get dropped. Idioms are the usual casualties. The first German draft of this very post called the run-on sitemap a „Textwurst“, a text sausage, and it didn't survive my review.
The knottier problem is keeping two versions of a post in step. If I fix a sentence in English next year, the German goes stale without saying so. So every translated post is logged in the Claude session with a fingerprint of the English text it was translated from. If a change is made to the source text it gets backported to the translated version, but for now this is triggered manually.
Making a page properly German
The process of translation and localisation is more than what's visible on the page, however. There's a smaller set of priorities under the hood, too. In the case of screen readers, every piece of text on a web page can say which language it is in, which the screen reader uses to choose a voice.
Read English with a German voice, or German with an English one, and it sounds unintentionally comical. So the German article has to declare that it's German, and anything inside it that stayed English must declare that it's English. That addresses the cover's image prompt, and any sidenote or image caption that hasn't been translated yet.
Elsewhere, the date isn't translated in the CMS at all. It's stored once, as a date rather than as words, and the site writes it out in the language of the page, so the German timestamp reads „5. September 2025“ instead of "5 September 2025". The "Explore with AI" links at the end of each post, which open the article in ChatGPT or Claude, send the German page and a German prompt, „Lies … und beantworte meine Fragen dazu“.
The link between the two versions took three attempts. The first was a plain text link. The second was a tinted pill with a little languages icon, which looked like a button that wanted attention. The third, and the one that seemed least obtrusive while still making its presence known, is a symbol and a link under the byline in the same crimson as the rest of the site's links.
Are localised pages visible on search?
Yes, German readers should be able to find German translated pages on search. Search engines find them through the sitemap, a file that lists every page on a site, and through a tag in each page that points to its twin in the other language.
Google's documentation (opens in a new window) describes that tag as a way to "point users to the most appropriate version of your page by language or region", so someone searching in German can be shown the German page.
Outside of search, people can find them in two places. One is the link beneath the byline on the English post. The other is a small "DE" next to the post's title in the archive, so a reader browsing the full list can see which posts have a German version.
Site search and the RSS feed are still English only. With a handful of German posts that's an acceptable compromise. A German search page or a German feed would be more machinery than that needs.
Some hiccups
Two things broke after the German pages went live.
The sitemap stopped displaying neatly. Firefox normally shows an XML file, the plain structured text a sitemap is written in, as an indented tree, and after the German pages arrived it showed one long run of text. The tags pairing each post with its German twin borrowed a bit of web-page code, and Firefox switches off its tidy view as soon as it sees any. Each page already declares its twin in its own code, so the pairing moved out of the sitemap and the tree came back.
The second came from an accessibility audit, run against every page on the live site at desktop width, at phone width and at phone width with larger text. One page failed. The German title of the Third Man post, „Abenteuer im Nachkriegseuropa“, has a word too long to fit on one line of a phone screen, and it pushed the whole page 49 pixels to the side. Post titles can now break an over-long word, and German titles hyphenate it where the browser knows how.
Any drag on performance?
A German page loads the same scripts, the same styles and the same fonts as its English twin. The only extra is the text itself, about three kilobytes more on a long post, because German runs longer than English. The page appears on screen just as quickly.
The umlauts and the German quotation marks needed nothing new either. They are in the font files the site already loads.
The work came to 17 small pull requests, which are bundles of code changes, each one reviewed before it went into the site. No new software libraries were added, and there's no separate German site to maintain.
What happens next
So that's the beginning of my adventures in localisation, and that's my minimum proof of concept to have a localisation workflow. Going forward, I'll select the oldest posts in the archive as candidates for translating into German, since the source copy is more or less settled and unlikely to change.
At some point the approach will need reconsideration. At around ten German posts, a German landing page starts to make sense, somewhere for German readers to start from. At around 15, the checks for stale translations should run on their own, and German search and a German feed become worth building.
The About and Privacy pages stay in English, meanwhile. A privacy notice is a statement I'm accountable for, so a German version would need a proper legal review before I could roll one out.
Vorsprung durch Technik. A leap forward through technology. I still need to work on my German language skills, though.
multi-block linocut print, a stocky British bulldog and a long German dachshund in strict side profile facing each other nose to nose, bold hand-carved relief lines capturing expressive facial wrinkles and coat texture, rich block-printed inks in warm fawn, deep chestnut, charcoal black, and crimson on heavyweight cotton paper, the bulldog's brow furrowed, the dachshund's chin raised, each with a plain speech bubble, the bulldog's reads "BLOG?" in bold stencil capitals, the dachshund's reads "Blog!" in German blackletter, generous empty space around both, subjects centredAbout the author


