Entity Enricher can produce enrichment results in up to 40 languages simultaneously. Multilingual fields are stored as language-keyed JSON objects — a format that is portable, queryable, and compatible with every major database.
In the schema editor, toggle the multilingual flag on any string or array-of-strings property. When enabled, the LLM returns values wrapped in a language-keyed object instead of a plain value.
multilingual: true in the JSON schema.multilingual: true). Use the ↑ button on any other chip to promote it as primary. The backend also filters out any stray language keys the LLM might emit that aren’t in your selection.dict[str, T], where keys are ISO 639-1 language codes and values match the field type.Multilingual values are stored as JSON objects with language codes as keys. This format was chosen over alternatives for its portability, queryability, and storage efficiency.
Fields without multilingual: true are returned as plain values. Identifiers, codes, URLs, dates, and numbers typically stay non-multilingual.
Two approaches exist for multilingual arrays. Entity Enricher uses Format A (language-keyed object) because it is the only format that works as-is across all major databases without transformation.
| Criteria | A Language-keyed object | B Array of localized items |
|---|---|---|
| Structure | {"en": [...], "fr": [...]} | [{"en": "x", "fr": "y"}, ...] |
| Query one language | Direct accessdata -> 'field' -> 'en' | Requires iterationjsonb_array_elements + extract |
| Add a language | Add one key to the object | Update every item in the array |
| Consistent with scalars | Yes — same {"en": "...", "fr": "..."} pattern | No — different shape for strings vs arrays |
| Database portability | All major databases | All major databases |
The language-keyed format is natively queryable in all major databases that support JSON columns.
40 languages are available. Select any combination when running an enrichment.
enEnglishzhChinesehiHindiesSpanisharArabicfrFrenchbnBengaliptPortugueseruRussianjaJapanesedeGermanurUrduviVietnamesetrTurkishkoKoreantaTamilmrMarathiteTelugupaPunjabiyueCantoneseitItalianplPolishukUkrainianroRomaniannlDutchelGreekcsCzechhuHungariansvSwedishsrSerbianbgBulgarianhrCroatianskSlovakdaDanishfiFinnishnoNorwegianltLithuanianslSlovenianlvLatvianetEstonianpreserve)The multilingual flag cannot be combined with the preserve flag: a preserved value passes through untranslated, in a single language. The schema editor disables the conflicting toggle, and the API rejects schemas carrying both flags. Key fields (natural or database keys) can be multilingual — entity identity then uses the schema's locked key language.
The multilingual flag is only valid on certain property types. The schema editor enforces this automatically.
| Property Type | Multilingual? | Output Format |
|---|---|---|
| string | Yes | dict[str, str] |
| number / integer | Yes | dict[str, float] |
| boolean | Yes | dict[str, bool] |
| array of primitives | Yes | dict[str, list[str]] |
| object | No | Mark individual fields inside the object instead — unless the object is one row per language, see below |
| array of objects | No | Mark individual fields inside items instead |
| $ref | No | Mark fields inside the referenced entity instead |
A multilingual value is a map of languages, not a single value — so attributes that constrain a single value cannot apply to it. These conflicts are resolved when the schema is generated and refused when you save one by hand, rather than failing later at enrichment.
A property restricted to a fixed set of members cannot also be multilingual: the members are canonical tokens, and a consumer database constrains a column against them. Translated labels belong in a lookup table of your own, keyed on the token.
A date, a UUID or a regex-checked code has one machine-readable form, not one per language. Saving a property that is both is rejected.
A preserved value is your data returned untouched, so there is nothing to translate.
This one is allowed. Identity is resolved in one language — fixed for the schema the first time it is published to a database — so a name can be translated without its identity moving.
Some sources model language as rows: a list where each item carries a language code and its own values, one per language. That is a different shape from a multilingual property, and the two must not be mixed. Generation recognises such a property as the object's language axis — only if every observed value really is a language code — and then turns the integrated mechanism off for that whole subtree. Marking individual fields inside the item, the usual advice for objects, is exactly the wrong remedy here: it would give you translations of rows that are already one per language.
One more distinction worth keeping straight: the languages you enrich into are a per-run choice; the language a schema's own prose is written in (its descriptions and labels) is fixed on the schema; and the language identity resolves in is fixed per database. Three separate settings that all sound like “the language”.
Multilingual support is woven into every stage of the enrichment pipeline.
When fusing results from multiple models, multilingual fields are compared per language.
| Scenario | Resolution |
|---|---|
| Models agree on English but differ on French | Not a disagreement. Identity is judged in the run's primary language, so this counts as agreement: English passes through, and French is settled by the per-language merge rule. Translation variance is never sent to an arbiter — paying a model to choose between two correct translations would be spending on nothing |
| One model has Arabic, another doesn't | Prefer the non-null value (Arabic is kept) |
| Multilingual arrays differ in length per model | Union of all items per language |