PhotoAtomic.Internationalization.Tool
0.6.0
dotnet tool install --global PhotoAtomic.Internationalization.Tool --version 0.6.0
dotnet new tool-manifest
dotnet tool install --local PhotoAtomic.Internationalization.Tool --version 0.6.0
#tool dotnet:?package=PhotoAtomic.Internationalization.Tool&version=0.6.0
nuke :add-package PhotoAtomic.Internationalization.Tool --version 0.6.0
PhotoAtomic.Internationalization.Tool
The CLI companion of
PhotoAtomic.Internationalization,
packaged as a dotnet tool. It opens your csproj with MSBuildWorkspace (Razor components
included), extracts the translation catalog from the T($"...") call sites, and lets you
manage translations before shipping instead of at runtime.
Installing and running
dotnet tool install -g PhotoAtomic.Internationalization.Tool
pai18n MyApp.csproj --csv translations.csv --all
# THE one command: prune, translate, lint,
# repair — and report what needs a human
pai18n MyApp.csproj content/rooms --csv translations.csv --all
# code AND content in one catalog
pai18n MyApp.csproj --csv translations.csv --verify
# CI-friendly: fails when the catalog has holes
Sources: code, and the content a compiler never sees
A source is a csproj (opened via MSBuildWorkspace, so source generators run and Razor
markup is included), a compiled assembly, or a .json catalog file — or a directory
of them — for text that is data: rooms written by an AI, rows in a database, a CMS export.
The format is just CatalogEntry written down, and downstream nothing can tell the
difference: vocabulary order, lint, repair and pruning work the same for both.
Name every source in the same run. --prune deletes the rows nothing asks for, so a run
that only knows about the code would delete every line the content says, and a run that only
knows the content would delete the program's own words. Sources are merged on
(key, context, kind), so a sentence said by both is one row.
Filling uses the same AI translation pipeline as
PhotoAtomic.Internationalization.AI
(configure the provider via appsettings / user secrets / environment variables); --verify is
meant for pipelines, so a missing translation breaks the build instead of surprising a user.
A scene is a chain: one thing, one name
When a catalog entry declares a Setting — the one line saying where a term lives, which
content knows and code does not — that line is also an identity. The units of one setting
are filled in order, each request carrying the terms the earlier ones settled on, so a
press and its base do not come back as a "pressa" and a "torchio". Different settings stay
side by side, and an entry with no setting at all (code, which has no such thing) is a chain
of one, so the parallelism is unchanged for everything that had it.
The glossary is seeded from the table before a single call is made: a name translated last
week must lead this run as firmly as one translated a second ago, otherwise a room drifts one
session at a time. Only the settled terms sharing a word with the key are shown
(Lexicon) — a model handed a dozen unrelated words starts working them in. A shared word is
found across punctuation too: a description is mostly punctuation, and "authority's writ,"
used to match neither "authority" nor "writ", so the scene's own word for a thing was judged
irrelevant to the sentence describing that very thing.
--all: the whole workflow, in the right order
--all deletes the rows for sentences the code no longer says, translates the values first
and the sentences after (sentences are declined against the words already translated — fill a
cold table in one pass and nothing is ever declined), then lints and repairs round after round
until the count stops falling. What is still wrong is printed and moved to the end of the
CSV, so opening the file lands on the work. Exit 0 when nothing is left, 4 when a human is
needed; a rerun with nothing to do makes no AI calls and leaves the file byte-identical.
The single steps stay available, for CI and for looking closer:
--verify— no AI: every unit has rows for every language, or exit 3;--lint— no AI: what the rows themselves get wrong (holes that never arrive or were invented, variants never declined, a set of variants with no plain row to fall back on, a value that forgot its gender, an example word left in the template, a translation that opens in lowercase where the source opens a sentence, a value carrying a capital it never declared, a common noun that brought its own article along, a sentence nobody says any more). Exit 4 on an error; warnings only inform;--fix— repairs what the lint found: from the table where the answer is already there, by re-asking the model with the complaint in hand where it is not, and lints again so the result is a number rather than a hope;--prune— deletes the dead sentences only (never values), rewriting the CSV. Pass the catalog that covers the whole table, or live rows will look dead.--top-up— asks only for the grammatical cases a translated sentence is missing, and leaves every row it already has untouched. Run it when the table has learnt something new about a language: the day one of its nouns is declared plural, every sentence that can host it needs a row it was never asked for, and redoing the whole unit would cost the most and throw away rows that were already right. Deliberate on purpose — a plain rerun must cost nothing, and a case the model keeps refusing would otherwise be re-asked quietly for ever.
Part of PhotoAtomic.Libraries.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
This package has no dependencies.