Skip to content

ChristianIvicevic/intl-watcher

🌐 intl-watcher plugin for Next.js

👪 All Contributors: 2 🤝 Code of Conduct: Kept 🧪 Coverage 📝 License: MIT 📦 npm version 💪 TypeScript: Strict

Showcase

Automatically scans your Next.js project's source files to manage internationalization (i18n) translation keys. It keeps your translation dictionaries up-to-date by extracting new keys, removing unused ones, and optionally partitioning keys into separate client and server dictionaries.

Note

Primarily designed for use with next-intl, this plugin can technically be adapted for other i18n libraries or frameworks that share a similar dictionary structure and access pattern in code.

Features

  • Automatic Extraction: Scans your project's source code for i18n keys.
  • Namespace Support: Handles nested i18n keys organized into namespaces for structured translations.
  • Dictionary Syncing: Automatically updates JSON dictionaries with new translation keys.
  • Unused Keys Handling: Warns or removes unused keys.
  • Client/Server Partitioning: Separates translation keys into client-side and server-side bundles.
  • Debounced Scanning: Efficiently handles rapid file changes.
  • Suppression Escape Hatch: Silence warnings for specific unsupported expression kinds while native support is pending.

Installation

Install the package via npm, yarn or pnpm:

npm install intl-watcher
# or
yarn add intl-watcher
# or
pnpm add intl-watcher

Usage

Wrap your Next.js configuration with the provided createIntlWatcher function:

// next.config.ts
import { createIntlWatcher } from 'intl-watcher'

const withIntlWatcher = createIntlWatcher({
	dictionaryPaths: ['./i18n/en.json', './i18n/de.json'],
})

export default withIntlWatcher({
	reactStrictMode: true,
	// other Next.js config options...
})

Single-Run Mode

For use cases where you need to perform a one-time sync without file watching (e.g., in CI/CD pipelines, custom build scripts, or pre-commit hooks), use the syncTranslationKeys function:

// scripts/sync-translations.ts
import { syncTranslationKeys } from 'intl-watcher'

syncTranslationKeys({
	dictionaryPaths: ['./i18n/en.json', './i18n/de.json'],
	// ... other options
})

Run this script manually or as part of your build process:

# Using ts-node
npx ts-node scripts/sync-translations.ts

# Using tsx
npx tsx scripts/sync-translations.ts

# In package.json scripts
{
  "scripts": {
    "sync-translations": "tsx scripts/sync-translations.ts"
  }
}

Use Cases

  • CI/CD Validation: Ensure translation keys are synchronized before deployment
  • Pre-commit Hooks: Automatically update dictionaries when committing changes
  • Custom Build Steps: Integrate into existing build pipelines
  • Testing: Programmatically verify translation coverage

Configuration Options

The following options apply to both createIntlWatcher and syncTranslationKeys:

Required Options

dictionaryPaths

  • Type: string[]
  • Description: Paths to JSON dictionary files for each language. These files will be managed and kept in sync with your source.

Shared Optional Options

defaultValue

  • Type: (key: string) => string
  • Default:
    (key) => `[NYT: ${key}]`
  • Description: Function that generates a default translation for new keys.

removeUnusedKeys

  • Type: boolean
  • Default: false
  • Description: When true, removes keys no longer found in source files; otherwise emits warnings.

scanDelay

  • Type: number
  • Default: 500
  • Description: Delay in milliseconds before re‑scanning after file changes.

tsConfigFilePath

  • Type: string
  • Default: tsconfig.json
  • Description: Path to tsconfig.json for project file resolution.

watchPaths

  • Type: string[]
  • Default: ['./src']
  • Description: Paths that the plugin watches to trigger rescans. This does not change which files belong to your TypeScript project; that is controlled by tsconfig.json via tsConfigFilePath.

useTabs

  • Type: boolean
  • Default: true
  • Description: Use tab characters for indentation. When false, spaces will be used instead (see tabWidth).

tabWidth

  • Type: number
  • Default: 4
  • Description: Number of spaces per indentation level. Only applies when useTabs is false.

suppressExpressionWarnings

  • Type: string[]
  • Default: []
  • Description: Expression kind names for which the unsupported-expression diagnostic is silenced. Each entry must match a kind name as reported in the warning — for example 'ConditionalExpression' or 'CallExpression'. Any entry that does not suppress at least one warning during a scan will itself emit a warning, prompting you to remove the stale entry.

Note

This option is intended as a temporary escape hatch while native support for a given expression kind is pending. Before adding a kind here, consider opening a feature request so that support can be added properly.

Non-Partitioning Mode (default)

applyPartitioning

  • Type: false
  • Default: false
  • Description: Default mode where keys are not split.

translationFunctions

  • Type: string[]
  • Default: ['useTranslations', 'getTranslations']
  • Description: Translation function name(s) to scan for keys.

Partitioning Mode

applyPartitioning

  • Type: true
  • Description: Enables splitting translation keys into separate client and server bundles.

partitioningOptions

  • Type: { clientFunction?: string; serverFunction?: string }
  • Default:
    {
      clientFunction: 'useTranslations',
      serverFunction: 'getTranslations'
    }
  • Description: Function names to use for extracting client vs server translation keys.

Dictionary Partitioning

When applyPartitioning is enabled, the plugin generates separate dictionaries for client and server bundles. For example:

locales/
├── en.json
├── en.client.json
└── en.server.json

This enables optimized bundle sizes and clearer separation of translations by environment.

Development

See .github/CONTRIBUTING.md, then .github/DEVELOPMENT.md. Thanks! 💖

Contributors

Christian Ivicevic
Christian Ivicevic
💻 🖋 📖 🤔 🚇 🚧 📆 🔧
Mark Lenser
Mark Lenser

🤔

About

Automated translation key extraction and dictionary management plugin for Next.js

Topics

Resources

License

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Sponsor this project

 

Contributors