Skip to content

Core concepts

View .md

An organization owns projects. Each project has its own languages, namespaces, keys, translations, API keys and CDN endpoint. Translation memories and glossaries belong to the organization and are assigned to projects.

A project is one translatable surface, typically one application or website. Languages, namespaces, keys, API keys and the CDN endpoint are all project-scoped. Two surfaces that share almost all copy fit one project with several namespaces. Separate release cycles or owners call for separate projects. See Projects.

en de pt-BR zh-Hant zh-Hant-TW

Locale codes are canonical BCP-47: subtags separated by a hyphen, the language lowercase, a script subtag Titlecase, a region subtag UPPERCASE. Underscore input such as pt_BR is accepted everywhere and canonicalized on entry, so the dashboard, API, CLI, import/export and CDN all return and display pt-BR. A project’s codes are valid BCP-47 by construction and go straight into app config, URLs and Intl. See Locale codes.

You pick the source language when you create the project. It cannot be changed afterwards, and machine translation quality and translation memory matches both depend on it, so choose the language your team writes in.

https://cdn.comvi.io/<project-token>/<language>.json # default namespace
https://cdn.comvi.io/<project-token>/<namespace>/<language>.json # any other namespace

A namespace is a group of keys that ships together. Every (language, namespace) pair becomes one JSON file on the CDN, so namespaces are the unit you code-split translations by. Every project starts with a default namespace; add more to load only what a screen needs, to keep a large project navigable, or to give teams their own area. See Namespaces.

greeting
nav.home
errors.not_found

Keys are opaque strings. Dot notation is a readability convention, not nesting. A key belongs to exactly one namespace and carries a value per language, plus an optional description that gives translators context. Values are ICU MessageFormat:

You have {count, plural, one {# message} other {# messages}}.

Every value has a status: not_translated, not_reviewed or translated. Status tracks review, not delivery. Saving a value from the editor sets it to not_reviewed, whoever saved it. Moving a value to translated is a separate click on the status badge and needs review permission. Imported values land as translated.

Deploying is a separate action. Once Content Deploy is on, every write schedules a deploy about 5 seconds later, and the bundle holds whatever matches the Filter by Status setting. An empty filter ships drafts too. See Translation lifecycle.

An API key authenticates the CLI, CI and any automation against the REST API. A key is scoped to one project and carries its own scopes, but on every request Comvi intersects those scopes with the permissions its creator holds right now. Demote the creator and the key loses the same access. Human users authenticate with sessions; see Roles & permissions.

Webhooks go the other direction, Comvi calling your server, and are verified with an HMAC signature rather than an API key. See Webhooks.