Docs · Features

Key-based projects and the change feed

A second kind of project for continuous localization. The unit of work is a string key rather than an uploaded file, and the deliverable is one key/value file per language, on demand, forever.

What it does#

Documents are a job: a file arrives, gets translated, gets delivered. Keys are a relationship: your product has strings, they change every week, and every release needs the current set in every language. A key-based project's content is a set of string keys instead of documents; the type is chosen when the project is created and cannot be changed afterward. A key's identity is its project, namespace, name and an optional context, so two files can define a key with the same name without colliding.

The important consequence is the change feed. Instead of asking "what does the whole catalogue look like now?" and diffing it yourself, you keep a cursor and ask "what happened since?" Creations, edits and deletions all come back as entries, including deletions, which most systems in this space cannot tell you about at all. Values support plural forms: each language gets exactly the grammatical forms it needs. Changing a key's source text automatically flags every language that already had a translation for review, so an edit can never silently ship a stale string.

Getting started#

  1. Create the project as key-based, with your target languages.
  2. Import your source file. The namespace defaults to the file name, so common.json and admin.json can both define the same key name without conflict.
  3. Translate with a workflow, or fill values by hand in the grid.
  4. Export one file per language per namespace: those are your build files.
  5. On the next release, import the new source file and repeat.
  6. In your pipeline, poll the change feed and act only on what moved.
project create "Acme Strings" --type key_based --customer-id 7 --targets de-DE
keys import --project 8 --file ./en/common.json
keys translate --project 8 --workflow 9 --locale de-DE
keys export --project 8 --locale de-DE --namespace common
keys changes --project 8 --cursor-file

Works with#

  • Documents: key values are ordinary segments under the hood, so everything the document pipeline does, status, QA flags, the editor, the export guard, applies to a key value for free.
  • Workflows: translating a key project runs a normal workflow over its keys, with the same run view and spend safety as a document run.
  • Translation memory: key values read from and write to translation memory exactly as document segments do.
  • Glossaries: glossary and do-not-translate checks fire on key values and surface as QA flags on the value.
  • Memory: corrections made in the key grid are evidence like any other post-edit, and feed the same distillation.
  • Evaluations: engines and workflows compared in the Lab are the same ones that translate keys.

Current limits#

Current limits

The change feed keeps a limited retention window; a consumer whose cursor is older than that is told to resync rather than given a confidently wrong "nothing changed."

Export shape follows what you ask for, never the data: naming a namespace always gives a build file with bare key names, omitting it always gives a fully qualified transport file. This is deliberate, so adding a key in a new namespace can never silently rewrite every lookup key in your product.

Cleanup, removing keys no longer present in the source, only runs on a source-language import, since a translation file is by nature a partial view of the key set.

Some languages have more or fewer grammatical plural forms than others; a value that provably cannot survive a round trip between file formats is reported rather than silently dropped.

An import never overwrites a value a person has already approved or edited; it is refused and reported by name instead, protecting sign-off from being clobbered by a re-import.

A string key can carry a small number of in-context images for a vision-capable engine to see as translation context; with a text-only engine, the image is stored for reviewers but skipped at translation time.

A key's context does not survive a JSON export and reimport cycle: it comes back as a new, context-less key of the same name. Keys carrying a context round-trip cleanly through the gettext (.po) format instead, so prefer gettext for a project that round-trips keys with contexts.