Project configuration¶
The general commands take every path as an argument. A project that runs them
every week writes its layout once, in localizzy.toml, and then names a
language code:
The file¶
localizzy init --root . writes a commented starter file. The file is found
from the working directory upward, or named with --config. It is parsed once
into frozen records: an unknown key is an error, not a silent default, and
relative paths are resolved against the directory that holds the file. Command
flags override it; built-in defaults fill whatever it leaves out.
[source]
language = "en"
locales = ["de", "fr", "es"]
[qt]
sources = ["src"] # directories or .pro files
out_dir = "i18n/fresh" # where qt extract writes
prefix = "app" # app_de.ts, app_de.qm
[catalogs]
dir = "i18n"
pattern = "app_{code}.ts"
fresh_dir = "i18n/fresh"
retired_dir = "i18n/retired"
report_dir = "i18n/upgrade"
[memories]
dir = "i18n/memories"
direct = ["{code}-ui.tmx"]
glossary = ["{code}-core.tmx"]
glossary_statuses = ["approved", "do-not-translate"]
[languages.es]
catalog = "es_MX"
memory = "es-419"
[translate]
endpoint = "https://api.openai.com/v1"
api_key_env = "OPENAI_API_KEY"
cache_path = ".localizzy/translation-cache.sqlite"
fallback_models = ["MODEL"]
temperature = 0.2
timeout = 300
style_file = "style.md" # optional guidance passed to the engine
[qt] serves qt scan and qt extract when they get no paths. The rest
serves the project commands.
Fresh and approved catalogs¶
Keep two sets of catalogs apart. qt extract writes the FRESH catalogs:
whatever lupdate finds in today's code. The APPROVED catalogs under
[catalogs].dir hold reviewed translations. [qt].out_dir defaults to
i18n/fresh, the same directory as [catalogs].fresh_dir, so qt extract
never writes into the approved catalogs; the upgrade does the
merge, with a retired file and a report. Keep the two pointing at the same
place if you change either. Setting [qt].out_dir to [catalogs].dir would
make qt extract merge straight into the approved catalogs the way plain
lupdate does.
How a code becomes paths and tags¶
For localizzy project upgrade es with the file above:
| Item | Resolved to |
|---|---|
| APPROVED | i18n/app_es.ts |
| FRESH | i18n/fresh/app_es.ts (or --fresh) |
| NEW | i18n/app_es.new.ts (or --out) |
| RETIRED | i18n/retired/app_es-<fresh>-<approved>.ts |
| Report | i18n/upgrade/app_es.json |
| Direct memories | i18n/memories/es-ui.tmx |
| Glossary memories | i18n/memories/es-core.tmx plus any --glossary |
| Catalog language | es_MX |
| Memory language | es-419 |
A code absent from [languages] uses the code for both tags. A configured
memory that does not exist is reported on stderr and skipped, except by
build_ui, which refuses to run without its glossary memories: their terms
would otherwise enter the project memory.
The two <...> parts of the RETIRED name are the first eight hex digits of
the SHA-256 of the FRESH and APPROVED files. The same pair of inputs therefore
always names the same file. Running the same upgrade again is allowed when it
retires exactly the same messages; if an existing retired file of that name
differs, the command stops with exit 2 rather than overwrite it.
The commands¶
project upgrade CODE ports APPROVED onto FRESH and writes NEW, RETIRED and
the report, as upgrade describes. --no-engine leaves new
strings pending. --in-place replaces APPROVED with NEW only when nothing is
left pending or untranslated. Otherwise NEW stays beside it for review and the
command exits 1 after writing NEW, RETIRED and the report. Usage errors exit 2.
project translate CODE fills APPROVED from its memories, then the engine,
and writes it back in place unless --out is given. --memory-only needs no
endpoint. --source-catalog i18n/fresh/app_en.ts starts a new language from
the source-language catalog; that keeps no existing translation, so it is
refused when the catalog of CODE already exists and --out is absent.
project build_ui CODE rebuilds the first [memories].direct file from the
approved catalog, leaving out pairs that the glossary memories already serve.
The engine model comes from --model, else the first fallback_models
entry; the rest of that list are the fallbacks. Without either, a command that
needs the engine stops with No model: pass --model or list fallback_models
under [translate]. [translate].style_file is resolved against the directory
of localizzy.toml.
The general commands (upgrade, translate, tm build_ui) still take
explicit paths and ignore localizzy.toml. Use them in scripts that own their
own layout.