Translations
Content entries can participate in a translation group so multiple locales stay linked. The API supports reading a linked translation and linking two existing entries in the same collection.
Read a linked translation (translation_locale)
On Get an Entry, pass translation_locale to fetch the entry that shares the same translation group in another locale.
- The path
uuidstill identifies the entry you start from. - The response is the other locale’s entry when a link exists.
- The entry at
uuidis loaded without astatefilter whentranslation_localeis present; the linked entry is then filtered bystate(samestatequery value you send).
Errors (404)
| Message | Meaning |
|---|---|
Translation not found for locale '{locale}'. | No linked entry in that locale. |
This entry has no translations linked. | The entry has no translation_group_id. |
Link two entries (link-translation)
Links two existing entries in the same collection that have different locales.
Request
POST /api/{collection}/{uuid}/link-translation HTTP/1.1
Host: app.nomacms.com
Content-Type: application/json
project-id: <project-uuid>
Authorization: Bearer <api-token>
Accept: application/jsonRequires the update ability on the token.
Path parameters
| Param | Description |
|---|---|
collection | Collection slug |
uuid | UUID of one of the entries to link (the “source” row) |
JSON body
| Field | Type | Description |
|---|---|---|
translation_entry_uuid | string (UUID) | The other entry’s UUID (must exist in the same collection and project) |
Response (200)
{
"message": "Translation linked successfully.",
"translation_group_id": 123
}Errors
| Status | When |
|---|---|
| 400 | Missing project-id or project cannot be resolved |
| 401 | Missing or invalid bearer token |
| 403 | Token does not have update (or *) |
| 404 | Collection or source entry not found |
| 422 | Translation UUID missing, entry not in collection, same entry, or same locale as the source |
| 429 | Rate limited |
The server uses the translation service to assign a shared translation group for both entries.
Singleton collections
When you create an entry in a singleton collection, the API may auto-link it with singleton entries in other locales for the same project (implementation in ContentEntryTranslationService). Treat that as a convenience for multilingual singletons; exact behavior follows your project’s locale setup.
Example
GET examples resolve the linked row via translation_locale (see Get an Entry). POST calls link-translation to connect two existing entries (EN_UUID / OTHER_UUID must differ in locale). Use one flow or the other as needed.
import { createClient } from "@nomacms/js-sdk"
const client = createClient({
projectId: process.env.NOMA_PROJECT_ID!,
apiKey: process.env.NOMA_API_KEY!,
})
const en = await client.content.get("blog-posts", enUuid, { state: "published" })
const tr = await client.content.get("blog-posts", enUuid, {
state: "published",
translation_locale: "tr",
})
await client.content.linkTranslation("blog-posts", enUuid, {
translation_entry_uuid: otherUuid,
})import axios from "axios"
const headers = {
"project-id": process.env.NOMA_PROJECT_ID!,
Authorization: `Bearer ${process.env.NOMA_API_KEY}`,
Accept: "application/json",
}
async function main() {
const base = `https://app.nomacms.com/api/blog-posts/${encodeURIComponent(enUuid)}`
const english = await axios.get(base, {
params: { state: "published" },
headers,
})
console.log(english.data)
const turkish = await axios.get(base, {
params: { state: "published", translation_locale: "tr" },
headers,
})
console.log(turkish.data)
const linked = await axios.post(
`${base}/link-translation`,
{ translation_entry_uuid: otherUuid },
{ headers: { ...headers, "Content-Type": "application/json" } },
)
console.log(linked.data)
}
void main()<?php
$slug = 'blog-posts';
$enUuid = getenv('EN_UUID');
$basePath = '/api/' . rawurlencode($slug) . '/' . rawurlencode($enUuid);
$hdr = [
'project-id: ' . getenv('NOMA_PROJECT_ID'),
'Authorization: Bearer ' . getenv('NOMA_API_KEY'),
'Accept: application/json',
];
// GET — linked translation (Turkish)
$query = http_build_query([
'state' => 'published',
'translation_locale' => 'tr',
]);
$ch = curl_init('https://app.nomacms.com' . $basePath . '?' . $query);
curl_setopt_array($ch, [
CURLOPT_HTTPHEADER => $hdr,
CURLOPT_RETURNTRANSFER => true,
]);
echo curl_exec($ch) . "\n";
// POST — link translation
$body = json_encode(['translation_entry_uuid' => getenv('OTHER_UUID')]);
$ch = curl_init('https://app.nomacms.com' . $basePath . '/link-translation');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $body,
CURLOPT_HTTPHEADER => array_merge([
'Content-Type: application/json',
'Content-Length: ' . strlen($body),
], $hdr),
CURLOPT_RETURNTRANSFER => true,
]);
echo curl_exec($ch);# GET — fetch linked entry in another locale (path uuid = source entry)
curl -sS -G "https://app.nomacms.com/api/blog-posts/${EN_UUID}" \
--data-urlencode "state=published" \
--data-urlencode "translation_locale=tr" \
-H "project-id: $NOMA_PROJECT_ID" \
-H "Authorization: Bearer $NOMA_API_KEY" \
-H "Accept: application/json"
# POST — link two entries as translations
curl -sS -X POST "https://app.nomacms.com/api/blog-posts/${EN_UUID}/link-translation" \
-H "Content-Type: application/json" \
-H "project-id: $NOMA_PROJECT_ID" \
-H "Authorization: Bearer $NOMA_API_KEY" \
-H "Accept: application/json" \
-d "{\"translation_entry_uuid\":\"${OTHER_UUID}\"}"package main
import (
"bytes"
"encoding/json"
"io"
"net/http"
"net/url"
"os"
)
func main() {
host := "https://app.nomacms.com/api/blog-posts/" + url.PathEscape(os.Getenv("EN_UUID"))
hdr := func(req *http.Request) {
req.Header.Set("project-id", os.Getenv("NOMA_PROJECT_ID"))
req.Header.Set("Authorization", "Bearer "+os.Getenv("NOMA_API_KEY"))
req.Header.Set("Accept", "application/json")
}
// GET — linked translation
u, _ := url.Parse(host)
q := u.Query()
q.Set("state", "published")
q.Set("translation_locale", "tr")
u.RawQuery = q.Encode()
req, _ := http.NewRequest("GET", u.String(), nil)
hdr(req)
do(req)
// POST — link translation
payload, _ := json.Marshal(map[string]string{
"translation_entry_uuid": os.Getenv("OTHER_UUID"),
})
req, _ = http.NewRequest("POST", host+"/link-translation", bytes.NewReader(payload))
hdr(req)
req.Header.Set("Content-Type", "application/json")
do(req)
}
func do(req *http.Request) {
res, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
_, _ = io.Copy(os.Stdout, res.Body)
}require "net/http"
require "json"
require "uri"
slug = "blog-posts"
en_uuid = ENV.fetch("EN_UUID")
base = URI("https://app.nomacms.com/api/#{slug}/#{en_uuid}")
headers = {
"project-id" => ENV.fetch("NOMA_PROJECT_ID"),
"Authorization" => "Bearer #{ENV.fetch('NOMA_API_KEY')}",
"Accept" => "application/json"
}
# GET — linked translation
get_uri = base.dup
get_uri.query = URI.encode_www_form("state" => "published", "translation_locale" => "tr")
req = Net::HTTP::Get.new(get_uri)
headers.each { |k, v| req[k] = v }
Net::HTTP.start(get_uri.hostname, get_uri.port, use_ssl: get_uri.scheme == "https") do |http|
puts http.request(req).body
end
# POST — link translation
post_uri = URI("https://app.nomacms.com/api/#{slug}/#{en_uuid}/link-translation")
req = Net::HTTP::Post.new(post_uri)
req["Content-Type"] = "application/json"
headers.each { |k, v| req[k] = v }
req.body = JSON.generate("translation_entry_uuid" => ENV.fetch("OTHER_UUID"))
Net::HTTP.start(post_uri.hostname, post_uri.port, use_ssl: post_uri.scheme == "https") do |http|
puts http.request(req).body
endimport json
import os
import urllib.parse
import urllib.request
slug = "blog-posts"
en_uuid = os.environ["EN_UUID"]
path = f"/api/{urllib.parse.quote(slug, safe='')}/{urllib.parse.quote(en_uuid, safe='')}"
base = f"https://app.nomacms.com{path}"
hdr = {
"project-id": os.environ["NOMA_PROJECT_ID"],
"Authorization": f"Bearer {os.environ['NOMA_API_KEY']}",
"Accept": "application/json",
}
# GET — linked translation
q = urllib.parse.urlencode({"state": "published", "translation_locale": "tr"})
req = urllib.request.Request(
f"{base}?{q}",
headers=hdr,
method="GET",
)
with urllib.request.urlopen(req) as res:
print(res.read().decode())
# POST — link translation
body = {"translation_entry_uuid": os.environ["OTHER_UUID"]}
req = urllib.request.Request(
f"{base}/link-translation",
data=json.dumps(body).encode(),
headers={**hdr, "Content-Type": "application/json"},
method="POST",
)
with urllib.request.urlopen(req) as res:
print(res.read().decode())Related
- Get an Entry -
translation_locale - JavaScript SDK -
content.get,content.linkTranslation