blazor-loc is a Roslyn-based CLI that understands both BlazorLocalization's Translation() API and Microsoft's built-in IStringLocalizer["key"] + .resx. No code changes or adoption required — point it at any IStringLocalizer project and go.
inspect— Translation health audit. See every translation key, where it's used, what's missing, what conflicts, and how complete each locale is.extract— Scan your codebase and export every source string. Run it in CI on every merge to keep your translation platform in sync.
dotnet tool install -g BlazorLocalization.ExtractorTo upgrade to the latest version:
dotnet tool update -g BlazorLocalization.ExtractorRun with no arguments to launch the interactive wizard. It walks you through project selection, export format, and output destination:
blazor-locWithout tooling, keeping translations in sync means manually copying strings between your code and your translation platform — every key, every language, every time something changes. extract scans your entire codebase and exports every source string in one command. Run it locally or in CI on every merge.
Extract to Crowdin i18next JSON (the default format):
blazor-loc extract ./src -o ./translationsExtract to GNU Gettext PO (includes source file references for translator context):
blazor-loc extract ./src -f po -o ./translationsExtract to stdout (pipeable — outputs in the requested format):
blazor-loc extract ./src -f poExport translations for a single locale to stdout:
blazor-loc extract ./src -f po -l daScan a specific .csproj file instead of a directory:
blazor-loc extract ./src/MyApp/MyApp.csproj -o ./translationsScan multiple paths (directories or .csproj files):
blazor-loc extract ./src/WebApp ./src/Shared -o ./translationsWhen output is a directory, per-locale translations are automatically written as separate files (e.g. Project.da.i18next.json):
blazor-loc extract ./src -f i18next -o ./translationsTo suppress per-locale files and export source strings only (useful when uploading to Crowdin — translators should provide translations, not your inline source texts):
blazor-loc extract ./src -f i18next -o ./translations --source-onlyNarrow to specific locales:
blazor-loc extract ./src -f i18next -o ./translations -l da -l es-MXPoint inspect at your project and get a translation health audit — the full picture across every file, locale, and pattern in seconds.
blazor-loc inspect ./srcTranslation entries — one row per unique key, showing where it's used in your code, its source text, which form it takes (simple, plural, select...), and which locales have a translation. Spot a key that's missing de when every other row has it.
Conflicts — same key used with different source texts in different places. Almost always a bug. The table shows exactly which files disagree and what each one says.
Extraction warnings — the handful of calls the scanner couldn't confidently resolve. Things like Loc[someVar ? Loc["..."] : Loc["..."]] or mangled expressions that somehow made it through code review. By default, only these problem cases surface — not the hundreds of healthy calls.
Locale coverage — per-language summary: how many keys each locale has, what percentage that covers, and any keys that only exist in one locale but not the source. At a glance you see that es-MX is at 97.6% but vi is at 85.7%.
Cross-reference summary — one line bridging code and data: how many keys resolved, how many are missing, how many .resx entries have no matching code reference.
See full key/value tables per language (instead of the default summary):
blazor-loc inspect ./src --show-resx-localesSee every line of code where a translation was found (including all healthy ones):
blazor-loc inspect ./src --show-extracted-callsOutput as JSON (auto-enabled when stdout is piped):
blazor-loc inspect ./src --json
blazor-loc inspect ./src | jq '.translationEntries[] | select(.status == "Missing")'| Format | Flag | Best for |
|---|---|---|
| Crowdin i18next JSON | -f i18next |
Uploading to Crowdin or any i18next-compatible platform. Flat key/value, lightweight. |
| GNU Gettext PO | -f po |
Maximum translator context — includes #: source references and #. comments. |
| Generic JSON | -f json |
Debugging and custom tooling. Full-fidelity export with all metadata. |
New formats are easy to add — the exporter is a simple interface. PRs welcome.
Automate extraction in CI so translation files stay in sync with your code:
- name: Install blazor-loc
run: dotnet tool install -g BlazorLocalization.Extractor
- name: Extract source strings
run: blazor-loc extract ./src -f i18next -o ./translations
- name: Upload translations
uses: crowdin/github-action@v2
with:
upload_sources: true
source: translations/*.i18next.jsonWhen the same key appears with different source texts, the extractor flags it as a conflict:
# Fail the build on duplicate keys (useful in CI)
blazor-loc extract ./src --exit-on-duplicate-key
# Keep the first-seen source text (default)
blazor-loc extract ./src --on-duplicate-key first
# Skip conflicting keys entirely
blazor-loc extract ./src --on-duplicate-key skipFor all available flags and options:
blazor-loc extract --help
blazor-loc inspect --helpSee also: Examples for Translation() usage · Configuration for setup