<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Deuwi]]></title><description><![CDATA[Deuwi]]></description><link>https://deuwi.hashnode.dev</link><generator>RSS for Node</generator><lastBuildDate>Wed, 04 Nov 2026 00:19:24 GMT</lastBuildDate><atom:link href="https://deuwi.hashnode.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Stop shipping hard‑coded strings: Meet i18nGuard — an i18n linter for JS/TS (i18next, React‑Intl, Lingui)]]></title><description><![CDATA[Internationalization (i18n) issues are sneaky. A single hard‑coded string slips into a PR, a key is missing in one locale, another key stays unused for…]]></description><link>https://deuwi.hashnode.dev/stop-shipping-hardcoded-strings-meet-i18nguard-an-i18n-linter-for-jsts-i18next-reactintl-lingui</link><guid isPermaLink="true">https://deuwi.hashnode.dev/stop-shipping-hardcoded-strings-meet-i18nguard-an-i18n-linter-for-jsts-i18next-reactintl-lingui</guid><category><![CDATA[React]]></category><category><![CDATA[ts]]></category><category><![CDATA[i18n]]></category><dc:creator><![CDATA[Deuwi]]></dc:creator><pubDate>Tue, 23 Sep 2025 08:02:56 GMT</pubDate><content:encoded><![CDATA[<p>Internationalization (i18n) issues are sneaky. A single hard‑coded string slips into a PR, a key is missing in one locale, another key stays unused for months — and users get a half‑translated UI.</p>
<p>What if your tooling could catch these problems automatically — across frameworks — locally and in CI, and even help you fix them inside VS Code?</p>
<p>Meet i18nGuard: an internationalization linter and validation tool for JavaScript/TypeScript projects that supports i18next, React‑Intl (FormatJS), and Lingui. It ships with a CLI, a VS Code extension, SARIF reporting for code scanning, pseudo‑localization, and translation coverage budgets.</p>
<ul>
<li><p>GitHub: <a target="_blank" href="https://github.com/deuwi/i18nGuard">deuwi/i18nGuard</a></p>
</li>
<li><p>npm (CLI): <a target="_blank" href="https://www.npmjs.com/package/@i18nguard/cli">@i18nguard/cli</a></p>
</li>
</ul>
<blockquote>
<p>TL;DR</p>
<ul>
<li><p>Detect hard‑coded strings, missing keys, and unused keys</p>
</li>
<li><p>Works with i18next, React‑Intl (FormatJS), and Lingui</p>
</li>
<li><p>CLI for local/CI, VS Code extension for one‑click fixes</p>
</li>
<li><p>JSON/HTML/SARIF reports and coverage thresholds</p>
</li>
</ul>
</blockquote>
<hr />
<h2 id="heading-why-another-i18n-tool">Why another i18n tool?</h2>
<p>Most teams rely on ad‑hoc linters or per‑framework scripts. i18nGuard aims to be:</p>
<ul>
<li><p>Framework‑aware: i18next, React‑Intl, Lingui — one tool, consistent results</p>
</li>
<li><p>Dev‑friendly: instant feedback in VS Code with Quick Fixes</p>
</li>
<li><p>CI‑ready: SARIF output, budgets, and fail‑on‑error for PR gates</p>
</li>
<li><p>Practical: pseudo‑localization and actionable reports</p>
</li>
</ul>
<hr />
<h2 id="heading-key-features">Key features</h2>
<ul>
<li><p>Smart detection of hard‑coded strings in UI</p>
</li>
<li><p>Validation of missing and unused keys across locales</p>
</li>
<li><p>Multi‑framework adapters: i18next, React‑Intl, Lingui</p>
</li>
<li><p>VS Code integration (real‑time diagnostics + Quick Fix)</p>
</li>
<li><p>CI/CD friendly: JSON/HTML/SARIF reports, fail‑on‑error</p>
</li>
<li><p>Pseudo‑localization and translation coverage budgets</p>
</li>
</ul>
<hr />
<h2 id="heading-quick-demo">Quick demo</h2>
<ul>
<li><p>Run a CLI scan and get a concise summary of i18n issues</p>
</li>
<li><p>Open the HTML report or upload SARIF to GitHub code scanning</p>
</li>
<li><p>In VS Code, use Quick Fix to externalize strings and write keys to catalogs</p>
</li>
</ul>
<blockquote>
<p>Tip: Include a short GIF showing <code>i18nguard scan</code> and a Quick Fix in VS Code.</p>
</blockquote>
<hr />
<h2 id="heading-quick-start">Quick Start</h2>
<p>Install the CLI globally or as a dev dependency:</p>
<pre><code class="lang-plaintext"># Global
npm install -g @i18nguard/cli

# Project
npm install --save-dev @i18nguard/cli
</code></pre>
<p>Create an <code>i18nscan.config.ts</code> at your project root:</p>
<pre><code class="lang-plaintext">import { defineConfig } from '@i18nguard/core';

export default defineConfig({
  library: 'i18next', // or 'formatjs' or 'lingui' or 'auto'
  src: ['src/**/*.{ts,tsx,js,jsx}'],
  locales: ['en', 'fr', 'es'],
  defaultLocale: 'en',
  catalogs: {
    i18next: {
      pathPattern: 'public/locales/{locale}/{ns}.json',
      namespaces: ['common', 'auth', 'dashboard']
    }
  },
  budgets: {
    coverage: {
      fr: 95,
      es: 80
    },
    maxNewHardCodedPerPR: 0
  },
  ignore: ['**/*.test.*', '**/node_modules/**'],
  keygen: {
    strategy: 'filePathSlug',
    maxLen: 60
  },
  report: {
    formats: ['json', 'html'],
    outputDir: 'reports/i18n'
  }
});
</code></pre>
<p>Run a scan:</p>
<pre><code class="lang-plaintext"># Basic scan
i18nguard scan

# JSON and HTML reports
i18nguard scan --format json --output results.json
i18nguard report --input results.json --format html --output report.html
</code></pre>
<p>Prefer using the latest dev build?</p>
<pre><code class="lang-plaintext"># Clone and build for latest features
git clone https://github.com/deuwi/i18nGuard.git
cd i18nGuard
pnpm install
pnpm build

# Run via pnpm filter without global install
pnpm --filter @i18nguard/cli exec i18nguard scan
</code></pre>
<hr />
<h2 id="heading-vs-code-extension-highlights-v110">VS Code extension highlights (v1.1.0)</h2>
<ul>
<li><p>Real‑time diagnostics for hard‑coded strings, missing and unused keys</p>
</li>
<li><p>Quick Fix to externalize strings and write keys to translation catalogs</p>
</li>
<li><p>Framework‑aware generation (i18next, React‑Intl, Lingui)</p>
</li>
<li><p>Multi‑locale defaults:</p>
<ul>
<li><p>Writes source text to the default locale (e.g., <code>en</code>)</p>
</li>
<li><p>Writes <code>TODO:Translate(source)</code> to other locales (e.g., <code>fr</code>, <code>es</code>)</p>
</li>
</ul>
</li>
<li><p>Namespace‑aware (i18next), Windows‑friendly paths</p>
</li>
<li><p>Precise highlighting of string literals (not whole calls)</p>
</li>
<li><p>Progress feedback and clear status messages</p>
</li>
</ul>
<blockquote>
<p>Marketplace listing is coming; you can install the VSIX locally if you build from the repo.</p>
</blockquote>
<hr />
<h2 id="heading-cicd-and-sarif">CI/CD and SARIF</h2>
<p>Catch i18n issues on every PR with GitHub Actions:</p>
<pre><code class="lang-plaintext">name: i18n Validation
on: [push, pull_request]

jobs:
  i18n:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: npm ci
      - run: npx i18nguard scan --format sarif --output i18n.sarif --fail-on-error
      - name: Upload SARIF (GitHub code scanning)
        uses: github/codeql-action/upload-sarif@v3
        with:
          sarif_file: i18n.sarif
</code></pre>
<p>Budgets help you enforce translation quality:</p>
<ul>
<li><p><code>maxNewHardCodedPerPR: 0</code> to block new hard‑coded strings</p>
</li>
<li><p>Per‑locale coverage thresholds to keep catalogs healthy</p>
</li>
</ul>
<hr />
<h2 id="heading-configuration-examples">Configuration examples</h2>
<p>Next.js:</p>
<pre><code class="lang-plaintext">export default defineConfig({
  library: 'i18next',
  src: ['pages/**/*.{ts,tsx}', 'components/**/*.{ts,tsx}'],
  catalogs: {
    i18next: {
      pathPattern: 'public/locales/{locale}/{ns}.json',
      namespaces: ['common', 'navigation']
    }
  }
});
</code></pre>
<p>Create React App:</p>
<pre><code class="lang-plaintext">export default defineConfig({
  library: 'i18next',
  src: ['src/**/*.{ts,tsx,js,jsx}'],
  catalogs: {
    i18next: {
      pathPattern: 'src/locales/{locale}.json', // No namespaces
      namespaces: ['translation']
    }
  }
});
</code></pre>
<p>FormatJS / React‑Intl:</p>
<pre><code class="lang-plaintext">export default defineConfig({
  library: 'formatjs',
  src: ['src/**/*.{ts,tsx,js,jsx}'],
  locales: ['en', 'fr', 'es'],
  defaultLocale: 'en',
  catalogs: {
    formatjs: {
      messagesGlobs: ['src/locales/{locale}.json']
    }
  }
});
</code></pre>
<p>Lingui:</p>
<pre><code class="lang-plaintext">export default defineConfig({
  library: 'lingui',
  src: ['src/**/*.{ts,tsx,js,jsx}'],
  locales: ['en', 'fr', 'es'],
  defaultLocale: 'en',
  catalogs: {
    lingui: {
      pathPattern: 'src/locales/{locale}/messages.po'
    }
  }
});
</code></pre>
<hr />
<h2 id="heading-roadmap">Roadmap</h2>
<ul>
<li><p>VS Code: FormatJS and Lingui support in the extension</p>
</li>
<li><p>GitHub Action: turnkey action with inputs and PR comments</p>
</li>
<li><p>Advanced ICU validation and watch mode</p>
</li>
<li><p>Pseudo‑localization enhancements in the CLI</p>
</li>
</ul>
<p>Contributions are welcome — check the repo for open issues and ideas.</p>
<hr />
<h2 id="heading-get-started">Get started</h2>
<ul>
<li><p>Install the CLI: <code>npm i -D @i18nguard/cli</code> (or global)</p>
</li>
<li><p>Add <code>i18nscan.config.ts</code> and run <code>i18nguard scan</code></p>
</li>
<li><p>Try the VS Code extension locally</p>
</li>
<li><p>Wire it into CI with SARIF for code scanning</p>
</li>
<li><p>GitHub: <a target="_blank" href="https://github.com/deuwi/i18nGuard">deuwi/i18nGuard</a></p>
</li>
<li><p>npm (CLI): <a target="_blank" href="https://www.npmjs.com/package/@i18nguard/cli">@i18nguard/cli</a></p>
</li>
<li><p>Sponsor: <a target="_blank" href="https://github.com/sponsors/deuwi">GitHub Sponsors</a></p>
</li>
</ul>
<p>If you found this useful, drop a ⭐ on GitHub and share feedback — it helps a lot!</p>
]]></content:encoded></item></channel></rss>