<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: taha farzalizadeh</title>
    <description>The latest articles on DEV Community by taha farzalizadeh (@tahafarzalizadeh).</description>
    <link>https://dev.to/tahafarzalizadeh</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4095773%2Fb1b3c991-dd85-4b4e-9cf6-fd87ee67949a.png</url>
      <title>DEV Community: taha farzalizadeh</title>
      <link>https://dev.to/tahafarzalizadeh</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/tahafarzalizadeh"/>
    <language>en</language>
    <item>
      <title>i18n-doctor: Find Unused, Missing, and Hardcoded Translation Keys in JS/TS</title>
      <dc:creator>taha farzalizadeh</dc:creator>
      <pubDate>Wed, 26 Aug 2026 14:05:19 +0000</pubDate>
      <link>https://dev.to/tahafarzalizadeh/i18n-doctor-find-unused-missing-and-hardcoded-translation-keys-in-jsts-10mi</link>
      <guid>https://dev.to/tahafarzalizadeh/i18n-doctor-find-unused-missing-and-hardcoded-translation-keys-in-jsts-10mi</guid>
      <description>&lt;p&gt;Internationalization (i18n) breaks quietly. Keys rot in locale files. Screens ship with English hardcoded in JSX. Another locale is missing half the catalog. Most teams only notice this in production — or never.&lt;br&gt;
&lt;strong&gt;i18n-doctor&lt;/strong&gt; is an open-source static analyzer for JavaScript and TypeScript that finds those problems without running your app.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;One-line definition: i18n-doctor checks your source and locale files for unused keys, missing keys, duplicates, cross-locale gaps, and untranslated UI text — then reports them in the CLI or live in your editor.&lt;/p&gt;
&lt;h2&gt;
  
  
  The problem i18n-doctor solves
&lt;/h2&gt;

&lt;p&gt;Modern frontends rarely call &lt;code&gt;t("key")&lt;/code&gt; in one simple place. Keys are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;passed down as props (&lt;code&gt;{ t }&lt;/code&gt;, &lt;code&gt;props.t&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;built from static pieces (&lt;code&gt;"HELLO_" + "AGAIN"&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;partly dynamic (&lt;code&gt;t("HELLO_" + suffix)&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;mixed across React, Vue, Angular, Next.js, i18next, react-intl, vue-i18n, next-intl, Lingui, and more
Regex scripts and “search the repo” workflows miss those patterns. Manual review does not scale. Locale files grow, CI stays green, and translation debt compounds.
## Why I built it
I kept hitting the same gap: great i18n &lt;em&gt;libraries&lt;/em&gt;, but weak &lt;em&gt;hygiene tooling&lt;/em&gt; that understands real usage — including IDE feedback while you type, not only a CI script after the fact.
So I built &lt;strong&gt;i18n-doctor&lt;/strong&gt; as:&lt;/li&gt;
&lt;li&gt;a &lt;strong&gt;CLI&lt;/strong&gt; you can run with &lt;code&gt;npx&lt;/code&gt; or in CI&lt;/li&gt;
&lt;li&gt;a shared &lt;strong&gt;language server&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;thin &lt;strong&gt;VS Code&lt;/strong&gt; and &lt;strong&gt;JetBrains / WebStorm&lt;/strong&gt; plugins on top of that server
Same analyzer everywhere — terminal, PR checks, and the editor.&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;h2&gt;
  
  
  What it detects today
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Finding&lt;/th&gt;
&lt;th&gt;Meaning&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Unused keys&lt;/td&gt;
&lt;td&gt;Defined in locales, never referenced in code&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Missing keys&lt;/td&gt;
&lt;td&gt;Used in code, missing from locales&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Duplicate keys&lt;/td&gt;
&lt;td&gt;Same key defined more than once&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cross-locale gaps&lt;/td&gt;
&lt;td&gt;Present in one locale, absent in another&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Untranslated text&lt;/td&gt;
&lt;td&gt;Hardcoded JSX / UI strings that never go through a translator (info by default)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;It also handles harder static cases:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;prop-passed translators&lt;/li&gt;
&lt;li&gt;statically concatenated keys&lt;/li&gt;
&lt;li&gt;soft “may be unused” hints when a dynamic usage might still cover a key
Analysis is &lt;strong&gt;static only&lt;/strong&gt; — no runtime, no bundler, no side effects.
## Try it in 10 seconds
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx i18n-doctor check
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Or install as a dev dependency and wire a script:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-D&lt;/span&gt; i18n-doctor
&lt;span class="c"&gt;# package.json → "i18n:check": "i18n-doctor check"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And the result:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;· Discovering project…
· Loading configuration…
· Detecting framework…
· Collecting sources &amp;amp; usages…
· Analyzing locale coverage…
✓ Done (2376ms)
i18n-doctor issues
Root: PATH/TO/YOUR/PROJECT

Summary
  Unused:    1152
  Missing:   34
  Duplicate: 3
  Total:     1189

Locale coverage
  Base: en  Locales: en, fa
  Coverage: 99.56%
  Missing in other langs: 18
  Extra (not in base): 17
  en  100%  (2040/2040 keys)
  fa  99.1%  (2022/2040 keys)

"and the unused or duplicated keys locations here"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Prefer live underlines while editing? Install the editor extension (bundled language server — no project dependency required):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;VS Code Marketplace → search &lt;strong&gt;i18n-doctor&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;JetBrains Marketplace → search &lt;strong&gt;i18n-doctor&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ftnmzlw0ll3st4md7c1tn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ftnmzlw0ll3st4md7c1tn.png" alt=" "&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Development path (where this is going)
&lt;/h2&gt;

&lt;p&gt;i18n-doctor is currently in &lt;strong&gt;beta (v0.9.x)&lt;/strong&gt;. The path so far:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Core analyzer&lt;/strong&gt; — unused / missing / duplicate / coverage&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CLI + reports&lt;/strong&gt; — terminal, JSON, SARIF, Markdown, HTML&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Language server&lt;/strong&gt; — shared engine for editors&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;VS Code + JetBrains plugins&lt;/strong&gt; — live diagnostics&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Smarter usages&lt;/strong&gt; — prop-passed &lt;code&gt;t&lt;/code&gt;, static composition, dynamic softening, untranslated UI text
Next focus areas: more frameworks and edge cases, better suppressions/config ergonomics, and IDE features beyond diagnostics (hover / actions) when the analyzer is solid enough.
Feedback from real projects is the fastest way to stabilize toward v1.
## Who should use it&lt;/li&gt;
&lt;li&gt;Teams shipping multi-locale React / Vue / Next / Angular apps&lt;/li&gt;
&lt;li&gt;Maintainers cleaning up large locale JSON / catalogs&lt;/li&gt;
&lt;li&gt;Anyone who wants i18n checks in &lt;strong&gt;CI and&lt;/strong&gt; the editor from one tool
If your translations matter to users, your keys deserve the same static scrutiny as TypeScript types.
## Links&lt;/li&gt;
&lt;li&gt;GitHub: &lt;a href="https://github.com/taha-farzalizadeh/i18n-doctor" rel="noopener noreferrer"&gt;https://github.com/taha-farzalizadeh/i18n-doctor&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;npm (&lt;code&gt;i18n-doctor&lt;/code&gt; / CLI): &lt;a href="https://www.npmjs.com/package/i18n-doctor" rel="noopener noreferrer"&gt;https://www.npmjs.com/package/i18n-doctor&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Issues / feedback: &lt;a href="https://github.com/taha-farzalizadeh/i18n-doctor/issues" rel="noopener noreferrer"&gt;https://github.com/taha-farzalizadeh/i18n-doctor/issues&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;VS Code extension: search &lt;strong&gt;i18n-doctor&lt;/strong&gt; on the &lt;a href="https://marketplace.visualstudio.com/vscode" rel="noopener noreferrer"&gt;Visual Studio Marketplace&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;JetBrains / WebStorm plugin: search &lt;strong&gt;i18n-doctor&lt;/strong&gt; on the &lt;a href="https://plugins.jetbrains.com" rel="noopener noreferrer"&gt;JetBrains Marketplace&lt;/a&gt;
If you try it on your repo, open an issue with what it missed — that feedback shapes the beta.
---&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>javascript</category>
      <category>typescript</category>
      <category>i18</category>
      <category>devtools</category>
    </item>
  </channel>
</rss>
