PostShare
EngineeringMarch 30, 2026·9 min

Building Bilingual Apps: Our Approach to EN/ES Localization

RC

Rashad Cureton

Founder, Cure Consulting Group

Building Bilingual Apps: Our Approach to EN/ES Localization
Back to Blog

Why Most Bilingual Apps Feel Broken

You've seen them — apps where the Spanish version is clearly an afterthought. Buttons that overflow because "Submit" became "Enviar formulario de solicitud." Date formats that show MM/DD/YYYY to users who expect DD/MM/YYYY. Currency symbols in the wrong position.

At Cure Consulting Group, bilingual support isn't a feature we bolt on at the end. It's an architectural decision we make on day one. Every product we ship — from Vendly serving LATAM merchants to this very website — is designed for English and Spanish from the ground up.

Here's exactly how we do it.

Architecture First: The Dictionary Pattern

The foundation of our i18n architecture is the dictionary pattern. Instead of scattering translated strings throughout your code, you centralize all text in structured dictionary files.

For our Next.js projects (like this website), the structure looks like this:

src/
  dictionaries/
    en.json
    es.json
  app/
    [lang]/
      page.tsx
      layout.tsx

Each dictionary is a nested JSON object organized by feature:

json
{
  "hero": {
    "title": "We Build What You Need",
    "subtitle": "Custom software for businesses that...",
    "cta": "Start Your Project"
  },
  "services": {
    "title": "Our Services",
    "sprint": {
      "name": "Sprint",
      "description": "MVP in 4-6 weeks"
    }
  }
}

The Spanish dictionary mirrors this structure exactly. If a key exists in English, it must exist in Spanish. We enforce this with TypeScript — our dictionary type is generated from the English file, and the Spanish file must satisfy the same interface.

Dynamic Routing for Language

We use Next.js middleware to detect the user's preferred language and route accordingly:

  • Browser detection: Check the Accept-Language header on first visit
  • URL-based: /en/services vs /es/services
  • Persistent preference: Store the choice in a cookie so it persists

The key insight: language is a route parameter, not a state variable. This means every page has a unique URL per language, which is critical for SEO. Google can index both versions independently.

Beyond String Translation: Cultural Adaptation

Translation is maybe 40% of localization. The rest is cultural adaptation:

Date and Number Formatting

In the US: March 10, 2026 / $1,500.00 In Latin America: 10 de marzo de 2026 / $1.500,00

Notice the decimal and thousands separators swap. We use the Intl API for all formatting:

typescript

Get insights like this in your inbox

Practical tips on AI, mobile & cloud — no spam.

const formatter = new Intl.NumberFormat(lang === 'es' ? 'es-419' : 'en-US', {
  style: 'currency',
  currency: 'USD'
});

We use es-419 (Latin American Spanish) rather than es-ES (Spain Spanish) because our clients primarily serve LATAM markets.

Text Expansion

Spanish text is typically 20-30% longer than English. This isn't trivial — it affects:

  • Button widths: "Submit" vs. "Enviar solicitud"
  • Navigation labels: "Services" vs. "Servicios" (fine), but "Settings" vs. "Configuración" (problematic in tight spaces)
  • Table columns: Headers that fit in English may wrap in Spanish

Our solution: design for the longer language first. If the Spanish version looks good, the English version will always fit. We learned this the hard way on Vendly, where merchant dashboard labels overflowed on smaller screens.

Formality and Tone

English has one "you." Spanish has "tú" (informal) and "usted" (formal). For business software, we default to "usted" — it's safer and more professional across LATAM regions. But for consumer apps targeting younger demographics, "tú" feels more natural.

We document this decision in our style guide per project. Mixing formal and informal address within an app is jarring and unprofessional.

Pluralization Rules

English has two plural forms (1 item, 2 items). Spanish also has two, but the rules differ for some edge cases. More importantly, languages like Arabic have six plural forms. If you might localize beyond EN/ES later, use ICU MessageFormat from the start:

{count, plural,
  one {# resultado encontrado}
  other {# resultados encontrados}
}

Mobile Considerations

For our Kotlin and Swift projects, localization follows platform conventions:

Android (Kotlin)

  • String resources in res/values/strings.xml and res/values-es/strings.xml
  • Plurals handled with resources
  • Layout direction handled automatically by the system
  • We use Jetpack Compose's stringResource() exclusively — no hardcoded strings

iOS (Swift)

  • .strings files or String Catalogs (new in Xcode 15+)
  • String(localized:) for all user-facing text
  • Auto Layout handles text expansion naturally with proper constraints

The discipline is the same on both platforms: never hardcode user-facing text. Every string goes through the localization system, even during prototyping. Adding i18n retroactively is ten times more expensive than building it in from the start.

Testing Bilingual Apps

Our testing process includes:

  • Pseudo-localization: Replace all strings with accented versions (e.g., "[Sërvïcës]") to catch hardcoded text that bypassed the localization system.
  • Length testing: Run the app with 30% longer strings to catch overflow issues.
  • Native speaker review: Machine translation is a starting point, never the final product. Every Spanish string in our apps is reviewed by a native LATAM Spanish speaker.
  • Cultural review: Screenshots reviewed for cultural appropriateness — imagery, color associations, iconography.
  • Format testing: Verify dates, numbers, currency, and phone numbers display correctly per locale.

SEO for Bilingual Websites

For our Next.js sites, bilingual SEO requires:

  • hreflang tags: Tell Google which page is the English version and which is Spanish
  • Separate meta descriptions: Translate and adapt, don't just mirror
  • Localized URLs: /en/services and /es/servicios (translate the slugs too)
  • Language-specific sitemaps: Or a single sitemap with hreflang annotations

This website implements all of these. Check the page source — you'll see the hreflang tags in the head.

The Cost of Getting It Right (and Wrong)

Adding bilingual support from the start adds approximately 15-20% to frontend development cost. That's the cost of maintaining two dictionary files, testing both languages, and handling text expansion in the UI.

Adding bilingual support retroactively? 40-60% of the original frontend cost, because you're refactoring components that assumed a single language.

For businesses serving the US Hispanic market (63 million people, $3.2 trillion in GDP), that 15-20% upfront investment is one of the highest-ROI decisions you can make.


Building a bilingual product? Book a free consultation — we'll review your architecture and help you plan localization that scales.

i18nLocalizationSpanishReactNext.js
RC

Written by

Rashad Cureton

Founder & Principal Engineer

Rashad is the founder of Cure Consulting Group. Previously an engineer at JP Morgan, Ford, Clear, NYT, Kickstarter, and Big Nerd Ranch. He builds full-stack web and mobile apps for startups and companies of every size.

Found this useful?

Book a free 30-minute architecture review to discuss your project.

Book a Review

Related Articles