CLIFF in Five Minutes
CLIFF (Contextual Localization Integrated File Format) 1.0 is a plain-text localization format designed for both AI and human review. Instead of smuggling meaning into key names, it states — in readable, machine-checkable fields — which text this is, what type it has, which tone it carries, what state it is in and what context surrounds it.
This page covers only what you need while using the plugin. The authoritative specification lives in the cliff-format repository (spec/cliff-1.0.0.md and spec/abnf/cliff-1.0.abnf).
File skeleton
CLIFF 1.0 # version line: first non-blank, non-comment line; case sensitive
namespace: my-game # header: project/product identifier
clan: settings # header: semantic family (one file = one clan)
source-language: en-US
target-language: zh-Hans
[video] # section line: dots express nesting; write the full path
context: "Video settings screen." # group metadata (only context/type/emotion/max-width)
type: label
emotion: [objective]
max-width: 12
<resolution> # entry line: a stable id inside angle brackets
source: "Resolution" # required
target: "分辨率"
status: final # required
- Order is mandatory: version line → header fields → zero or more sections.
- Indentation carries no meaning; fields may be completely flat and blank lines are purely cosmetic.
- Comments are whole lines starting with
#(optional leading whitespace). There are no inline comments and no PO-style#./#:markers.
Header fields
| Field | Required | Meaning |
|---|---|---|
namespace | ✅ | First segment of the canonical ID, lowercase kebab-case (comes from the CLIFF Namespace setting) |
clan | ✅ | Semantic family; resolves to a UE Namespace through the mapping table |
source-language | ✅ | BCP 47 source language |
target-language | ✅ | BCP 47 target language (must match the directory/file layout) |
version | ⛔ | Source content/project version such as "1.4.2" (not the CLIFF spec version) |
variant | ⛔ | standard (default) or glossary |
title / info / standard | ⛔ | Family title, family notes, translation standard (the AI translation uses standard as guidance) |
dependency | ⛔ | A list of dependent file paths, e.g. ["../shared/terms.zh-Hans.cliff"] |
x-… | ⛔ | Extension fields; strict validators warn but never reject |
NOTE
namespace+clan+ group path + entry id form the canonical ID:my-game.settings.video.resolution. It must be unique within the file, and duplicates are a hard error — never last-wins.
Groups and inheritance
A section line such as [video.advanced] carries the full dotted path (there are no nested brackets and no closing marker). The only group metadata keys allowed before the first entry are context, type, emotion and max-width.
| Field | Inherited | Rule |
|---|---|---|
context | ✅ | Group value followed by entry value, joined with a single space |
type | ✅ | Entry overrides group; at least one of them must exist |
emotion | ✅ | Entry overrides group (lists are not merged) |
max-width | ✅ | Entry overrides group |
source / target / status / reference / reviewer | ⛔ | Never inherited; source and status are required per entry |
Value shapes
In CLIFF the shape is the type — there are no shortcuts:
type: label # tag: bare, never quoted
status: final # tag
emotion: [calm, polite] # list: brackets are mandatory
reference: ["src/ui.cpp:42"] # list: brackets even for a single item
max-width: 24 # positive integer
source: "Hello " "world" # adjacent strings concatenate to "Hello world"
target: "Line 1\nLine 2" # only \n inside a string produces a real line break
WARNING
Writing
emotion: calm(missing brackets),type: "label"(a quoted tag) orreference: "src/ui.cpp:42"(a list as a scalar) are all validity errors in CLIFF 1.0. Multi-line text uses adjacent string concatenation or\n; there is no|-style block scalar.
Closed vocabularies
The vocabularies are closed: values outside them are rejected.
| Field | Count | Values |
|---|---|---|
type | 26 | Word level: noun verb adjective adverb pronoun numeral preposition conjunction particle interjection proper-noun; phrase level: noun-phrase verb-phrase adjective-phrase adverb-phrase fixed-phrase idiom; text level: sentence description narration dialogue monologue prompt label subtitle accessibility-cue |
emotion | 23 | neutral objective mechanical joyful sad angry fearful surprised curious disgusted anxious calm playful serious urgent romantic hopeful grateful formal informal polite rude nostalgic |
status | 4 | initial (no target) translated reviewed final |
variant | 2 | standard glossary |
When emotion is omitted, the default follows type: dialogue / monologue / idiom → [neutral], everything else → [objective]. Full meanings are in vocabularies and mapping.
ICU and placeholders
CLIFF defines no placeholder syntax of its own: ICU MessageFormat (both MF1 and MF2) inside source / target is passed through verbatim. The single hard rule is that any string containing { or } must have balanced braces, and obviously malformed ICU should be rejected.
<inbox-count>
source: "{count, plural, =0 {No new messages} one {# new message} other {# new messages}}"
target: "{count, plural, =0 {没有新消息} other {# 条新消息}}"
type: sentence
status: reviewed
NOTE
UE’s
FText::Formatdoes not evaluate ICU semantics. The plugin passes strings through untouched and disables format validation while compiling.locres(EGenerateLocResFlags::None), so ICU text can live safely in UE and be interpreted by your runtime or by external tools.
File naming and layout
The header is authoritative and the file name and directory must agree with it — any mismatch fails validation:
<target-language>/<clan>.cliff # directory layout (what the plugin exports)
zh-Hans/settings.cliff
ja/settings.cliff
<clan>.<target-language>.cliff # flat layout (fine for small projects)
settings.zh-Hans.cliff
Encoding rules: UTF-8 (a BOM is accepted and ignored on input; canonical output is BOM-free), LF line endings (CRLF is accepted; a bare CR is invalid).
Validation
The built-in FCliffDocument::ParseAndValidate matches the Python reference cliff_format.validate(). Issues fall into seven categories: syntax, semantic, vocabulary, icu, id, extension and warning — and extension plus warning never count as failure.
| Category | Examples |
|---|---|
syntax | version line not CLIFF 1.0, unterminated string, a list split across lines, unknown escape, an entry before any section |
semantic | missing source / status / effective type, duplicated header field, translated without target, a disallowed key in group metadata |
vocabulary | type: paragraph, emotion: Sadness, status: Final (spelling and case must be exact) |
id | duplicated group path, duplicated entry id, an id with capitals or underscores |
icu | unbalanced braces |
extension | x- extension fields (warning only) |
warning | status: initial carrying a target; a translation exceeding max-width when width checking is enabled |
How CLIFF maps onto UE
| CLIFF | UE | Notes |
|---|---|---|
clan | UE Namespace | Resolved through the Clan to Namespace table (e.g. display-name → UObjectDisplayNames) |
<group-path>.<entry-id> | UE Key | Restored verbatim from the sidecar when present, otherwise derived from the group path and id |
source | manifest source text | Written as the FLocTextHelper source |
target | archive translation | status: initial writes the manifest only |
type / emotion / status / context | archive KeyMetadataObj | Persisted under cliff.* keys; UE has no equivalent fields |
Details: semantic mapping and key sidecar. Next: Dashboard workflow.