Go somewhere.

Home Page About Page Projects Page CV Page Dev Page Journal Page Contact Page Astro for Documentation and a Professional Site Dev Codex anywhere with tmux, Mosh, Termius, and Tailscale Dev Observing Codex MCP Tool Calls with Langfuse Dev Localization in Product Apps Dev MCP as a Safe AI Integration Boundary Dev Zod, OpenAPI, and Swagger for API Contracts Dev pg-boss for Durable Background Jobs Dev pgvector and RAG, Explained Through a Real Knowledge Workflow Dev Pragmatic Drag and Drop for Real Ordering Tasks Dev Prisma and PostgreSQL as the Product Source of Truth Dev Ralph Loop as a Plan Queue Dev React Router for Full-Stack Product Workflows Dev shadcn-Style UI as an Owned Product System Dev Dense Operational UI with Tables and Editors Dev Terminal Spike: a Native Android Terminal Dev Input Chinese pinyin with tones on Linux with fcitx Dev How to configure the DEFT Pro trackball on Linux Dev Use Pocket (read it later) on KOReader Dev Vercel AI SDK with Explicit Tool Boundaries Dev Vertical Slice Architecture with Dependency-Cruiser Dev Testing Product Workflows with Vitest and Playwright Dev Zod Beyond Validation Dev The Brothers Karamazov is the best novel I have ever read Journal Oral history of two Christians in a Chinese labour camp in the 1960s Journal The Word in the Bible Journal We love because He first loved us, not meaningless self-love Journal Mom, let me take the blame for Dad's mistakes Journal My story with God Journal The world is far from God, close to China Journal The Five Love Languages and Extrovert Only Exist in Language Journal Personality types don't exist, life is not a matching game Journal Dangerous words, why psychology is impossible Journal The story of a Shenzhen worker in 2000 Journal A Conversation with a Driver in Ras Al Khaimah Journal Shadian: a 1975 conflict between Communist forces and Muslims in China Journal Documentaries About China Journal
← Dev/Engineering

Localization in Product Apps

Why localization is a product boundary that affects routes, validation, dates, permissions, and support.

Localization is not only replacing English strings with another language.

In a product app, language touches workflow. It changes labels, validation messages, dates, empty states, permissions copy, documentation, support notes, and sometimes the shape of a form. If those details are scattered, localization becomes risky and expensive.

The first boundary is text ownership. A component should not hide important product language in random inline strings if that text needs translation later.

const messages = {
  importStarted: "Import started.",
  importFailed: "Import failed. Check the error file and try again.",
};

This tiny example is not a full i18n system. It just shows the habit: product messages are data the app should be able to find, review, and replace.

Validation messages deserve special care. A generic error like “Invalid input” may be technically true, but it does not help the user fix the problem. A translated bad error is still a bad error.

Dates and numbers are another place where localization becomes product behavior. A status page should not make users guess whether 05/06/2026 means May 6 or June 5. Formatting should match the user’s locale, for example through Intl.DateTimeFormat, or the product should use an unambiguous format.

There is also a routing decision. Some apps need localized URLs. Some only need localized content behind the same route. That choice affects SEO, bookmarks, support links, analytics, and caching. I would not add multilingual routing unless the product actually needs it.

The trade-off is maintenance. A localization system adds files, keys, review steps, and testing needs. It can also make simple copy changes slower. That is why I prefer adding structure around the areas that matter first: validation, navigation, empty states, and high-risk workflows.

I also try to keep message keys close to the product concept, not the current English sentence.

Weak key: submitButtonText
Better key: request.submit.action

The better key describes the role of the message. The English copy can change without making the key meaningless.

I would start localization early if the product clearly needs multiple languages. I would wait if the product is still exploring basic workflow shape. Premature localization can make rough product changes slower.

The practical goal is simple: users should understand what happened, what they can do next, and what went wrong. Localization is part of that promise.