I shipped a Spanish entry point for BingWow today: Bingo Online Gratis.
The interesting part was the implementation shape. The app already had a guide route that worked well for English pages, so I wanted the Spanish page to reuse the same route, same card fetch logic, same JSON-LD builders, same sitemap path, and same internal-link rules.
That meant the change was mostly data, plus a small typed extension to the guide template.
The page is a typed content object
The guide now carries optional metadata and locale fields:
interface Guide {
slug: string;
title: string;
metaTitle?: string;
metaDescription?: string;
ogLocale?: string;
uiLocale?: 'es';
}
The Spanish page itself is a normal guide object:
{
slug: 'bingo-online-gratis',
title: 'Bingo Online Gratis',
metaTitle: 'Bingo Online Gratis Sin Registro',
ogLocale: 'es_MX',
uiLocale: 'es',
headline: 'Bingo Online Gratis, Sin Registro y Sin App',
}
That let the existing route keep generating the page, Open Graph metadata, FAQ JSON-LD, HowTo JSON-LD, internal guide links, card recommendations, and sitemap entry.
The route owns repeated interface text
The page body is Spanish content, but the shared template has repeated labels like "Updated", "Ready-Made Cards", and "Frequently Asked Questions".
I added a tiny label map keyed by uiLocale so the repeated labels switch to Spanish only for this page:
const labels = guide.uiLocale === 'es'
? {
updated: 'Actualizado',
readyMadeCards: 'Tarjetas listas',
faqs: 'Preguntas frecuentes',
howToPrefix: 'Cómo jugar',
}
: {
updated: 'Updated',
readyMadeCards: 'Ready-Made Cards',
faqs: 'Frequently Asked Questions',
howToPrefix: 'How to play',
};
The shared route still handles the layout. The Spanish guide only changes the content and labels it actually needs.
The AI-readable answer lives beside the page
BingWow keeps a short answer file at llms.txt. I added a direct Spanish answer there too, with the canonical URL set to the new page.
That gives crawlers and assistants a concise answer for terms like:
- bingo online gratis
- bingo gratis online
- jugar bingo online sin registro
- bingo virtual gratis
The live page and the answer file now point at the same canonical URL: https://bingwow.com/guides/bingo-online-gratis.
The checks caught a real content bug
The first CI run failed because the acronym guard read Spanish sentence starts as English acronyms:
-
Unlooked like a brokenUN -
Usalooked like a brokenUSA
The fix was to change the Spanish copy, not the test:
-
Un enlace...becameEnlace único... -
Usa 3x3...becameElige 3x3...
That is exactly why I like content tests in application repos. Editorial changes still move through the same quality gate as code.
What shipped
- Live page: Bingo Online Gratis
- Short AI answer: llms.txt
- Related no-signup English guide: Free online bingo with no signup
- Create flow: Create a custom bingo card
The production deployment passed TypeScript, ESLint, Jest coverage, Next.js build, bundle-size check, and production smoke tests before I treated the page as live.
Top comments (3)
The typed-object approach is honestly reasonable for one page, most i18n frameworks make you pay the full setup cost before you get anything.
That setup tax is why I built i1n (i1n.ai): npx i1n init, keep your strings where they are, one command AI-translates and generates typed definitions. No framework migration. When BingWow grows past a page or two of localized routes, the hand-rolled version starts hurting, that's the moment it pays off. Free tier if you want to poke at it.
Hi Guys, I'm SamTech a Developer Talent Connector. We're currently recruiting experienced Web Developers, Frontend Developers, Backend Developers, Full-Stack Developers, and App Developers for long-term collaborations with an American development team. This is a remote opportunity involving real international projects, with payments available in USD or local currency. If you're interested in learning more, reply to this comment and I'll be happy to share the details.
Some comments may only be visible to logged-in visitors. Sign in to view all comments.