Languages API
Every Languages action (4) and data model (2): endpoints, scopes, input, preconditions, events and examples.
The languages you work and publish in, and your translations.
Module code i18n · 4 actions · 2 data models · 4 events. A key or token never does more here than the person behind it can; row-level security applies exactly as in the app. Scopes: i18n (everything), i18n:read (read only) or i18n:<capability>.
Resources
| Resource | Table | List and read | POST | PATCH | DELETE |
|---|---|---|---|---|---|
translations | translation | /api/v1/translations | |||
workspace_languages | workspace_language | /api/v1/workspace_languages |
Lists take limit (up to 200), cursor, order (e.g. -created_at), fields and q; every other query parameter is a column filter: ?status=paid, ?total[gte]=100, ?id[in]=a,b, ?x=null.
Actions
| Action | Needs | What it does |
|---|---|---|
i18n.add_language | i18n:manage | Add a language |
i18n.remove_language | i18n:manage | Remove a language |
i18n.set_default_language | i18n:manage | Change the default language |
i18n.set_translation | i18n:write | Translate a record |
i18n.add_language
Add a language — Lets this workspace hold content in another language.
Needs i18n:manage · changes data
https://app.getera.io/api/v1/workspace_languages/actions/add_language- Canonical address:
POST /api/v1/actions/i18n.add_language
Input
| Field | Type | Required | Notes |
|---|---|---|---|
code | string | yes | Language code · Two letters, optionally with a region: tr, en, tr-TR. · max 12 |
label | string | yes | Name · max 60 |
is_default | boolean | Make it the default · What an untranslated record falls back to. |
Preconditions
The action is refused with 409 and one of these codes:
| Code | Refused when |
|---|---|
invalid_code | The code must look like tr, en or tr-TR. |
already_added | This workspace already speaks that language. |
Events it publishes: i18n.language_added, i18n.default_language_changed
What it writes: workspace_language (insert) — Adds the language to the workspace
curl -X POST https://app.getera.io/api/v1/workspace_languages/actions/add_language \
-H "Authorization: Bearer $ERA_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{"code":"Language code","label":"Name"}'{
"ok": true,
"result": "…",
"events": [
"i18n.language_added",
"i18n.default_language_changed"
]
}import { createEra } from "@getera/sdk"
const era = createEra({ apiKey: process.env.ERA_API_KEY })
const res = await era.workspaceLanguages.addLanguage({
code: "Language code",
label: "Name"
})era workspace_languages add_language \
--code "Language code" \
--label "Name"{
"name": "era__i18n__add_language",
"arguments": {
"code": "Language code",
"label": "Name"
}
}Errors: 401 no or expired credential · 403 the credential does not hold i18n:manage · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 invalid_code, already_added · 429 slow down
i18n.remove_language
Remove a language — Withdraws a language and deletes what was written in it.
Needs i18n:manage · removes or cannot be undone · asks a person to confirm when Era runs it
https://app.getera.io/api/v1/workspace_languages/actions/remove_language- Canonical address:
POST /api/v1/actions/i18n.remove_language
Input
| Field | Type | Required | Notes |
|---|---|---|---|
code | string | yes | Language · max 12 |
Preconditions
The action is refused with 409 and one of these codes:
| Code | Refused when |
|---|---|
not_added | This workspace does not speak that language. |
default_protected | The default language cannot be removed. |
Events it publishes: i18n.language_removed
What it writes: workspace_language (delete) — Removes the language; translation (delete) — Deletes everything written in it
curl -X POST https://app.getera.io/api/v1/workspace_languages/actions/remove_language \
-H "Authorization: Bearer $ERA_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{"code":"Language"}'{
"ok": true,
"result": "…",
"events": [
"i18n.language_removed"
]
}import { createEra } from "@getera/sdk"
const era = createEra({ apiKey: process.env.ERA_API_KEY })
const res = await era.workspaceLanguages.removeLanguage({
code: "Language"
})era workspace_languages remove_language \
--code "Language"{
"name": "era__i18n__remove_language",
"arguments": {
"code": "Language"
}
}Errors: 401 no or expired credential · 403 the credential does not hold i18n:manage · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 not_added, default_protected · 429 slow down
i18n.set_default_language
Change the default language — What an untranslated record falls back to.
Needs i18n:manage · changes data
https://app.getera.io/api/v1/workspace_languages/actions/set_default_language- Canonical address:
POST /api/v1/actions/i18n.set_default_language
Input
| Field | Type | Required | Notes |
|---|---|---|---|
code | string | yes | Language · max 12 |
Preconditions
The action is refused with 409 and one of these codes:
| Code | Refused when |
|---|---|
not_added | This workspace does not speak that language. |
already_default | It is already the default. |
Events it publishes: i18n.default_language_changed
What it writes: workspace_language (update) — Moves the default to this language
curl -X POST https://app.getera.io/api/v1/workspace_languages/actions/set_default_language \
-H "Authorization: Bearer $ERA_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{"code":"Language"}'{
"ok": true,
"result": "…",
"events": [
"i18n.default_language_changed"
]
}import { createEra } from "@getera/sdk"
const era = createEra({ apiKey: process.env.ERA_API_KEY })
const res = await era.workspaceLanguages.setDefaultLanguage({
code: "Language"
})era workspace_languages set_default_language \
--code "Language"{
"name": "era__i18n__set_default_language",
"arguments": {
"code": "Language"
}
}Errors: 401 no or expired credential · 403 the credential does not hold i18n:manage · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 not_added, already_default · 429 slow down
i18n.set_translation
Translate a record — Stores one record’s translatable fields in one language.
Needs i18n:write · changes data
https://app.getera.io/api/v1/translations/actions/set_translation- Canonical address:
POST /api/v1/actions/i18n.set_translation
Input
| Field | Type | Required | Notes |
|---|---|---|---|
entity_type | string | yes | Kind of record · max 60 |
entity_id | uuid | yes | Record |
language_code | string | yes | Language · max 12 |
values | string | yes | Fields · A JSON object keyed by field name. |
Preconditions
The action is refused with 409 and one of these codes:
| Code | Refused when |
|---|---|
not_added | This workspace does not speak that language. |
invalid_values | The fields must be a JSON object. |
unknown_field | That field is not declared translatable. |
Events it publishes: i18n.translated
What it writes: translation (update) — Writes the translated fields
curl -X POST https://app.getera.io/api/v1/translations/actions/set_translation \
-H "Authorization: Bearer $ERA_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{"entity_type":"Kind of record","entity_id":"ENTITY_ID","language_code":"Language","values":"Fields"}'{
"ok": true,
"result": "…",
"events": [
"i18n.translated"
]
}import { createEra } from "@getera/sdk"
const era = createEra({ apiKey: process.env.ERA_API_KEY })
const res = await era.translations.setTranslation({
entity_type: "Kind of record",
entity_id: "ENTITY_ID",
language_code: "Language",
values: "Fields"
})era translations set_translation \
--entity-type "Kind of record" \
--entity-id "ENTITY_ID" \
--language-code "Language" \
--values "Fields"{
"name": "era__i18n__set_translation",
"arguments": {
"entity_type": "Kind of record",
"entity_id": "ENTITY_ID",
"language_code": "Language",
"values": "Fields"
}
}Errors: 401 no or expired credential · 403 the credential does not hold i18n:write · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 not_added, invalid_values, unknown_field · 429 slow down
Data models
Translation
Table translation · Resource translations
GET /api/v1/translationsGET /api/v1/translations/{id}
| Column | Type | Nullable | Allowed values | References |
|---|---|---|---|---|
id | string (uuid) · uuid | |||
organization_id | string (uuid) · uuid | organization | ||
workspace_id | string (uuid) · uuid | workspace | ||
entity_type | string · text | |||
entity_id | string (uuid) · uuid | |||
language_code | string · text | |||
values | object · jsonb | |||
created_by | string (uuid) · uuid | yes | app_user | |
created_at | string (date-time) · timestamptz | |||
updated_at | string (date-time) · timestamptz |
Primary key: id
Unique: workspace_id, entity_type, entity_id, language_code
Checks:
CHECK ((jsonb_typeof("values") = 'object'::text))
WorkspaceLanguage
Table workspace_language · Resource workspace_languages
GET /api/v1/workspace_languagesGET /api/v1/workspace_languages/{id}
| Column | Type | Nullable | Allowed values | References |
|---|---|---|---|---|
organization_id | string (uuid) · uuid | organization | ||
workspace_id | string (uuid) · uuid | workspace | ||
code | string · text | |||
label | string · text | |||
is_default | boolean · bool | |||
is_active | boolean · bool | |||
sort_order | integer · int4 | |||
created_at | string (date-time) · timestamptz | |||
updated_at | string (date-time) · timestamptz |
Primary key: workspace_id, code
Checks:
CHECK ((code ~ '^[a-z]{2}(-[A-Za-z0-9]{2,8})?$'::text))
Events
Workflows and webhooks react to these events.
| Event | What happens | Payload |
|---|---|---|
i18n.default_language_changed | The language untranslated records fall back to changed. | from, to |
i18n.language_added | A workspace started speaking another language. | code |
i18n.language_removed | A language was withdrawn, and its translations with it. | code |
i18n.translated | A record was translated into a language. | entity_type, entity_id, language_code |