BETA STATUS: This tool is currently in beta. We welcome contributions and feedback to help improve it!
A command-line tool to analyze next-intl translations in Next.js projects. This tool helps you find unused and undeclared translations to keep your internationalization files clean and maintainable.
Disclaimer: This tool is not officially affiliated with or endorsed by the
next-intl
team. It is an independent analysis tool designed to help developers working with thenext-intl
library. See DISCLAIMER.md for more details.
- π Find unused translations: Identify translation keys that are declared but never used in your code
β οΈ Find undeclared translations: Detect translation keys that are used in code but not declared in translation files- π€ Detect hardcoded strings: Find user-facing text that should be translated
- π Comprehensive reporting: Get detailed reports with file locations and line numbers
- π Fast analysis: Efficient scanning of your entire project
- π― Next.js optimized: Specifically designed for Next.js projects using next-intl
- Go 1.21 or higher
git clone <repository-url>
cd next-intl-analyzer
go mod tidy
# Run directly without building
go run main.go analyze /path/to/your/project
git clone <repository-url>
cd next-intl-analyzer
go mod tidy
go build -o next-intl-analyzer
# Run the binary
./next-intl-analyzer analyze /path/to/your/project
git clone <repository-url>
cd next-intl-analyzer
go mod tidy
go install .
# Now you can run it from anywhere
next-intl-analyzer analyze /path/to/your/project
# If running directly with Go
go run main.go analyze /path/to/your/nextjs-project
# If you built the binary
./next-intl-analyzer analyze /path/to/your/nextjs-project
# If installed globally
next-intl-analyzer analyze /path/to/your/nextjs-project
# Analyze current directory
go run main.go analyze .
# Analyze specific project
go run main.go analyze /Users/username/projects/my-app
# Analyze with relative path
go run main.go analyze ../my-nextjs-app
# Test with the included test data
go run main.go analyze test-data
# Generate a markdown report
go run main.go analyze test-data --report
# Generate a markdown report with custom filename
go run main.go analyze test-data --report --report-file my-analysis-report.md
# Generate a report without console output
go run main.go analyze test-data --report --quiet
## CLI Flags
| Flag | Description | Default |
|------|-------------|---------|
| `--report` | Generate a markdown report file | `false` |
| `--report-file` | Custom filename for the markdown report | `next-intl-analysis-report.md` |
| `--quiet` | Suppress console output (useful when generating reports) | `false` |
## Report Generation
The tool can generate a detailed markdown report of the analysis results:
```bash
# Generate a report with default filename
go run main.go analyze /path/to/your/project --report
# Generate a report with custom filename
go run main.go analyze /path/to/your/project --report --report-file my-report.md
You can automate translation checking in your CI/CD pipeline using GitHub Actions. Here's an example workflow file (.github/workflows/translation-checks.yml
):
This workflow runs on push and pull requests, checks your translations, and uploads the report as an artifact.
The report includes:
- π Summary statistics with counts of total, used, unused, undeclared translations, and hardcoded strings
- π Per-locale analysis showing results for each language
- β Unused translations with file locations
β οΈ Undeclared translations with file locations and line numbers- π€ Hardcoded strings with file locations and line numbers
- π‘ Recommendations for maintaining clean translation files
See sample-report.md for an example of the generated report format.
The CLI tool performs the following analysis:
-
Scans translation files: Looks strictly for translation files in:
messages/*.json
(the only source of locales)
-
Scans source files: Analyzes JSX and TSX files for translation usage:
- Client-side patterns:
useTranslations('namespace')
andt('key')
calls - Server-side patterns:
getTranslations('namespace')
calls - Advanced patterns:
t.rich()
,t.markup()
,t.raw()
,t.has()
calls - Namespace context: Automatically builds full key paths (e.g.,
HomePage.title
)
- Client-side patterns:
-
Compares and reports:
- Identifies unused translations (declared but not used)
- Finds undeclared translations (used but not declared)
- Detects hardcoded strings (user-facing text that should be translated)
- Provides detailed reports with file locations and line numbers
The tool provides a comprehensive report including:
- π Summary statistics: Total, used, unused, undeclared translations, and hardcoded string counts
- β Unused translations: List of translation keys that are declared but never used
β οΈ Undeclared translations: List of translation keys used in code but not declared- π€ Hardcoded strings: List of user-facing text that should be translated
- π File locations: Exact file paths and line numbers for each issue
=== Next-intl Translation Analysis ===
π Overall Summary:
Total translations: 28
Used translations: 12
Unused translations: 16
Undeclared translations: 1
Hardcoded strings: 2
Locales analyzed: 2
π Per-locale Analysis:
π EN:
Total translations: 28
Used translations: 12
Unused translations: 16
Undeclared translations: 1
Hardcoded strings: 2
β Unused translations (16):
- Common.button.delete (in messages/en.json)
- Common.navigation.contact (in messages/en.json)
- Errors.notFound (in messages/en.json)
- Errors.serverError (in messages/en.json)
- Metadata.title (in messages/en.json)
- Metadata.description (in messages/en.json)
- Layout.language (in messages/en.json)
- Layout.switchLocale (in messages/en.json)
β οΈ Undeclared translations (1):
- About.undeclaredKey (used in src/components/ServerComponent.tsx:11)
π€ Hardcoded strings (2):
- Welcome to our application (used in src/components/UntranslatedComponent.tsx:13)
- About Us (used in src/components/UntranslatedComponent.tsx:20)
A translation is considered unused when:
- It exists in your translation files (e.g.,
messages/en.json
) - But it is not referenced anywhere in your JSX/TSX files through:
- Direct calls:
t('key')
- Extended API calls:
t.rich()
,t.markup()
, etc. - Dot notation:
t('namespace.key')
- Direct calls:
Parent namespace keys are automatically considered "used" if any of their children are used. For example, if you have:
{
"Common": {
"button": {
"save": "Save",
"cancel": "Cancel"
}
}
}
And you use t('Common.button.save')
in your code, both Common
and Common.button
are considered used.
A translation is considered undeclared when:
- It is referenced in your JSX/TSX files (e.g.,
t('key')
) - But it does not exist in your translation files for a specific locale
These are potential bugs where your code is trying to use translations that don't exist.
Hardcoded strings are:
- User-facing text embedded directly in your JSX/TSX files
- Text that should likely be translated but isn't using the translation system
- Usually found in:
- JSX content:
<h1>Welcome to our site</h1>
- Props like
title
,placeholder
, etc.:<input placeholder="Enter your name" />
- JSX content:
The analyzer uses various heuristics to detect text that looks like user-facing content rather than technical code.
0
: Analysis completed successfully with no issues found1
: Analysis completed but found unused translations, undeclared translations, or hardcoded strings2
: Error occurred during analysis
.json
files inmessages/
directory only
.jsx
files.tsx
files- Excludes
node_modules
and.next
directories
// Basic usage
const t = useTranslations('HomePage');
t('title') // Detected as HomePage.title
t('welcome') // Detected as HomePage.welcome
// Variable-assigned translation functions
const adminT = useTranslations('Admin');
adminT('created') // Detected as Admin.created
adminT('modified') // Detected as Admin.modified
// Destructuring pattern
const { t: pageT } = useTranslations('PageContent');
pageT('heading') // Detected as PageContent.heading
// Advanced usage
t.rich('message', {...}) // Rich text formatting
t.markup('content', {...}) // HTML markup
t.raw('content') // Raw content
t.has('key') // Optional message checks
// Server components
const t = await getTranslations('About');
t('title') // Detected as About.title
t('description') // Detected as About.description
// Variable-assigned with namespace
const adminT = await getTranslations('Admin');
adminT('users') // Detected as Admin.users
// Dot notation (fully qualified keys)
t('Common.button.save') // Detected as Common.button.save
t('About.title') // Detected as About.title
// Mixed usage with variables
const adminT = useTranslations('Admin');
adminT('Subscriptions.title') // Detected as Admin.Subscriptions.title
next-intl-analyzer/
βββ main.go # CLI entry point
βββ cmd/
β βββ analyze.go # Analyze command implementation
βββ pkg/
β βββ analyzer/
β βββ analyzer.go # Core analysis logic
β βββ parser.go # Translation file and source code parsing
β βββ constants.go # Constants for text analysis
βββ test-data/ # Test files for development
βββ reports/ # Generated reports directory
βββ go.mod # Go module file
βββ README.md # This file
go build -o next-intl-analyzer
go test ./...
go run main.go analyze test-data
As this tool is in beta, we actively welcome and encourage contributions! Whether it's bug fixes, feature enhancements, or documentation improvements, your help is greatly appreciated.
To contribute:
- Fork the repository
- Create a feature branch
- Make your changes
- Add tests if applicable
- Submit a pull request
Some areas where contributions would be particularly valuable:
- Support for more translation patterns and edge cases
- Performance optimizations for large codebases
- Extended testing with different Next.js project structures
- Improved hardcoded string detection heuristics
- next-intl - The internationalization library this tool analyzes (created by Creator)
- Next.js - The React framework this tool is designed for
- DISCLAIMER.md - Important legal disclaimers and third-party attributions
- LICENSE - This project's license