The English version of a newly-released Cache-Control analyzer showed Japanese text—its status read “新鮮” instead of “Fresh.” The mistake traced back to shared logic that returned hard-coded Japanese strings while the page supplied only English labels.

The developer builds a series of lightweight browser tools, each with an English page and a Japanese page that reuse the same parsing functions and core logic. Only the visible wording should differ. When the Cache-Control analyzer shipped, the English interface displayed the correct labels, but the values it rendered came from the logic layer, which still contained Japanese literals. No console errors appeared; the page looked normal, yet the information presented to English-speaking users was wrong.

Why shared logic can betray translation

The bug stemmed from a design choice: the core function that decides what to show returned literal strings in Japanese. The page layer, responsible for the surrounding English text, never got a chance to replace those values. Because the logic and the UI were split cleanly, the problem stayed invisible during testing—everything “worked” technically, even though the user-facing language was incorrect.

The downside is that the language used inside the shared module becomes the default for every front-end that consumes it. If a different language is required, the default becomes a hidden bug.

The fix: keys, packs, and a safety net

The author rewrote the architecture to separate concerns:

  • Message packs now hold all human-readable strings for each language.
  • Shared logic returns only symbolic keys, never raw text.
  • Pages look up the appropriate word from the relevant pack based on the key.

When a message must include a number, the new code uses a small function rather than a template string. This lets each language decide where the number belongs, accommodating differences in word order.

A simple static-analysis step was added as well: the build process scans shared files for Japanese characters. If any appear, the developer is alerted immediately, preventing hard-coded foreign text from slipping back in.

What the experience taught the author

  1. Translation acts as a review pass. While writing English messages, the author noticed that some Japanese equivalents were vague. Translating forced clearer phrasing in both languages.
  2. Shared functions that return strings lock in a language for everyone. If a function decides the language, any consumer that expects a different one inherits the mistake. The bug is not a UI glitch; it’s a logic flaw.

Recommendations for anyone maintaining multilingual tools

  • Return keys, not strings, from core functions. Let the UI layer handle localization.
  • Or pass the desired strings into the function as parameters. This keeps the logic agnostic of language.
  • Audit shared modules for hard-coded native-language text. A quick search for non-ASCII characters can surface hidden issues.
  • Add a build-time check for foreign characters in shared code. Early detection beats post-release confusion.

What to watch for next

Takeaway: If your project shares code between language versions, make sure the shared part never decides the wording. Let each page supply its own words, and you’ll avoid the embarrassment of an English page that accidentally speaks Japanese.