DEV Community

Odiri Teddie
Odiri Teddie

Posted on

10 Internationalization Mistakes Frontend Engineers Keep Making


Say internationalization (or i18n, if you’ve typed it enough times) to most people and their mind jumps straight to one thing: translating the text.

That’s part of it, sure. It’s nowhere near the whole thing.

Internationalisation is really about building your app so it can bend to new languages, regions, and cultural expectations later without you having to tear the architecture apart to get there. And in practice that reaches into far more than you’d expect — routing, layouts, how you format dates and currencies, accessibility, performance, right down to the shape of your backend APIs.

I’ve watched "let’s add a second language" land on a board as a small ticket, then quietly detonate once someone actually started on it. Turns out the codebase was full of assumptions nobody had written down. Buttons ran out of room, layouts buckled, dates came out wrong, the currency left people second-guessing what they were paying, and the whole navigation fell apart the moment it hit a right-to-left language.

Here’s the reassuring part: nearly all of this is avoidable once you know where to look.

So here are ten of the internationalization mistakes I see frontend engineers make again and again, and how to stay clear of each one.


1. Treating Internationalization as "Just Translation"

This one is the misconception the whole topic suffers from.

Translation is a single slice of internationalization, not the pie.

An app that’s genuinely internationalized has to account for a lot more:

  • Locale-specific date and time formatting
  • Currency and number formatting
  • Text direction (LTR and RTL)
  • Address formats
  • Phone numbers
  • Units of measurement
  • Local conventions and cultural expectations

For example, replacing:

<h1>Welcome</h1>
Enter fullscreen mode Exit fullscreen mode

with:

<h1>{t("welcome")}</h1>
Enter fullscreen mode Exit fullscreen mode

is a fine first step, but it barely scratches what building for a global audience actually asks of you.

Treat internationalization as an architectural decision, not a job you hand off to translators at the end.


2. Hardcoding User-Facing Strings

Few things make localization more painful than sprinkling hardcoded text across all your components.

Instead of:

<button>Checkout</button>
Enter fullscreen mode Exit fullscreen mode

store the text in your translation files:

<button>{t("checkout")}</button>
Enter fullscreen mode Exit fullscreen mode

The benefits are immediate:

  • Easier maintenance
  • Cleaner components
  • Consistent terminology
  • Simpler translation workflows
  • Room to scale as the app keeps growing

The moment a translator has to go spelunking through your source to find the strings, you know localization was never really part of the plan.


3. Concatenating Strings Together

Gluing strings together happens to work in English because English word order is fairly predictable.

Plenty of other languages aren’t so obliging.

Consider this:

"Hello " + user.name
Enter fullscreen mode Exit fullscreen mode

Looks innocent enough, until you remember that not every language drops the name in that same spot.

A better approach is using placeholders:

Hello {{name}}
Enter fullscreen mode Exit fullscreen mode

or ICU MessageFormat:

Hello {name}
Enter fullscreen mode Exit fullscreen mode

This gives translators complete control over sentence structure while keeping your code flexible.

The rule of thumb I’d hand anyone: translate whole sentences, never fragments.


4. Designing Layouts That Only Work in English

English is relatively compact.

Many other languages aren't.

A button that comfortably displays:

Settings
Enter fullscreen mode Exit fullscreen mode

may need to display something much longer in another language.

Likewise:

Account
Enter fullscreen mode Exit fullscreen mode

could become:

Paramètres du compte
Enter fullscreen mode Exit fullscreen mode

or another significantly longer phrase depending on the locale.

Lean on fixed widths, hardcoded spacing, or layouts squeezed too tight, and translated text will drag every one of those assumptions into the light.

Some good practices include:

  • Using flexible layouts
  • Avoiding fixed-width buttons where possible
  • Allowing text to wrap gracefully
  • Testing with longer translations during development

One of the simplest ways to uncover layout issues is to switch your application to a language known for longer words, such as German.


5. Forgetting About Right-to-Left Languages

Supporting Arabic or Hebrew involves much more than translating text.

Entire layouts often need to mirror.

Common issues include:

  • Navigation alignment
  • Icons pointing the wrong direction
  • Incorrect spacing
  • Misaligned forms
  • Broken flex layouts

Instead of writing:

margin-left: 16px;
Enter fullscreen mode Exit fullscreen mode

prefer logical properties:

margin-inline-start: 16px;
Enter fullscreen mode Exit fullscreen mode

Likewise:

Instead of:

padding-right
Enter fullscreen mode Exit fullscreen mode

use:

padding-inline-end
Enter fullscreen mode Exit fullscreen mode

Logical CSS properties flip themselves based on the text direction, which makes your layouts hold together in places physical properties would’ve broken.


6. Formatting Dates, Times, and Numbers Manually

Hardcoding a date format is a trap far more people fall into than you’d think.

For example:

07/03/2026
Enter fullscreen mode Exit fullscreen mode

Is that:

  • July 3rd?
  • March 7th?

The honest answer is that it depends entirely on where the person reading it lives.

Instead of manually formatting values, use the browser's internationalization APIs:

new Intl.DateTimeFormat(locale).format(date)
Enter fullscreen mode Exit fullscreen mode

The same applies to:

  • Time
  • Percentages
  • Decimal separators
  • Thousands separators

Hand the locale-specific formatting to the platform rather than rebuilding it badly yourself.


7. Assuming Every User Uses the Same Currency

Even applications written entirely in English may serve users from different countries.

Consider these:

  • United Kingdom → GBP (£)
  • United States → USD ($)
  • Canada → CAD ($)
  • Australia → AUD ($)

A dollar sign on its own tells you almost nothing about which currency you’re actually looking at.

Instead of manually formatting values:

"$25"
Enter fullscreen mode Exit fullscreen mode

use:

new Intl.NumberFormat(locale, {
  style: "currency",
  currency: "GBP",
})
Enter fullscreen mode Exit fullscreen mode

Now the price shows up the way someone in that region would actually expect to read it.


8. Ignoring Pluralization Rules

Pluralization is more complicated than adding an "s".

English has relatively simple rules:

  • 1 item
  • 2 items

Many languages have several plural forms.

Assume every language plays by English’s rules and, sooner or later, your translations start coming out grammatically wrong.

Most internationalization libraries support pluralization out of the box, often through ICU MessageFormat or similar syntax.

Take advantage of these features rather than trying to build plural logic yourself.


9. Shipping Every Translation to Every User

As your application supports more languages, translation files can become surprisingly large.

Loading every language during the initial page load wastes bandwidth and increases bundle size.

Instead:

  • Lazy-load translation files
  • Split translations into namespaces
  • Load only the active locale
  • Consider route-level translation loading

Going international shouldn’t come at the cost of how fast your app feels.

Nobody should be downloading resources they’re never going to use.


10. Waiting Until the End of the Project

Of everything on this list, this is the one that costs the most to fix.

A team builds the whole product around one language, ships it, and then someone in a meeting says:

"We need to support three more countries."

Suddenly everything needs revisiting:

  • Routing
  • URLs
  • Forms
  • Validation messages
  • API responses
  • SEO
  • Metadata
  • Content management
  • Layouts
  • Design system components

Bolting internationalization on after the fact is nearly always harder than having designed for it on day one.

Even if today it’s one language and one market, building with i18n in the back of your mind buys you room to grow later without a painful rewrite.


A Quick Internationalization Checklist

Before shipping a feature, ask yourself:

  • Are all user-facing strings externalized?
  • Are dates locale-aware?
  • Are numbers locale-aware?
  • Are currencies formatted correctly?
  • Does the layout handle longer translations?
  • Have you tested right-to-left layouts?
  • Are pluralization rules handled correctly?
  • Are translation files loaded efficiently?
  • Can your routing support multiple locales?
  • Would adding another language require changing application logic?

If you can say "yes" to those without wincing, you’re already in better shape than a lot of shipped projects.


Final Thoughts

Internationalization was never a "we’ll get to it" item. It’s a design principle, and it shapes how the whole thing gets built from the first commit.

The apps that get this right don’t just swap in translated strings — they feel native to whoever’s using them, wherever they are and whatever they speak. Getting there means treating layouts, formatting, accessibility, performance, routing, and plain user expectations as first-class parts of the build, not afterthoughts bolted to the side of the translation work.

None of this requires launching in ten languages to pay off. Even a single-market app is easier to live with when it’s built this way. And the day expansion into a new region does land on your desk, past-you will have quietly done present-you an enormous favour.

What’s the i18n gotcha that blindsided you at some point? Drop it in the comments — I’d genuinely like to hear it.

Top comments (1)

Collapse
 
luis_cruzy profile image
Luis Cruzy

I completely agree with the point about designing layouts that only work in English, and I've experienced this issue firsthand when trying to localize a web application for a French-speaking audience. The problem is that many frontend engineers, including myself, tend to design with English in mind, without considering the fact that other languages may require more space or have different formatting requirements. One approach I've found helpful is to use a combination of flexible layouts and automated testing to ensure that our application can handle longer text strings and different character sets. I'd love to hear more about how others have tackled this challenge - what are some best practices or tools that you've found useful for ensuring layout compatibility across different languages?