Write in several languages
On this page
What a language version is #
It has its own article id, its own versions, its own quality checks and its own label. primaryArticleIdon it names the article it belongs to, the one written from the brief.It is approved on its own, by a person. Approving the article does not approve its versions and the other way round. The label of a version is derived from the approval record of that version. The claims, their states and their sources are the article’s. Nothing is checked again, so a claim that is single-source in the article is single-source in every version. Each claim’s text is read in the version’s language. It is exported and delivered like any article, when it is approved, and arrives as its own draft. See Deliver to WordPress and Deliver to a custom site. It has no illustration of its own. A brief that asks for one makes it for the article only, and a version delivered to a site carries no picture.
The 22 languages #
| Code | Language |
|---|---|
en | |
es | |
fr | |
de | |
pt | |
it | |
nl | |
pl | |
sv | |
da | |
no | |
fi | |
cs | |
sk | |
hu | |
ro | |
el | |
tr | |
uk | |
ja | |
bhs | |
sl |
bhsis one language for Bosnian, Croatian and Serbian. The writer is told to write in Bosnian, Croatian or Serbian, Latin script, ijekavian. It is not an ISO 639-1 code, so that Brenzuri does not claim one of the three national standards. WordPress receivesbsfor it.A brief with one language accepts any code with no spaces as the language of the article. Language versions need every code, the article’s own included, to be one of these 22.
Ask for versions in a brief #
+, in the order to write them. A person picks them in the brief form; through the API they go in language.
curl -X POST "$BRENZURI_URL/api/v1/briefs" \
-H "Authorization: Bearer $BRENZURI_KEY" \
-H "Content-Type: application/json" \
-d '{
"topic": "Ferry operators agree on a single timetable for the northern route",
"angle": "What changes for commuters from November",
"purpose": "news",
"length": "standard",
"mustAppear": [
"the November start date"
],
"illustration": "none",
"language": "en+es+de"
}'The article is en;esanddeare versions of it.A code outside the 22, a code twice, a version equal to the article’s language, an empty part ( en+es+) and a space anywhere are refused with 422invalid_language. Codes in a list are lower-cased.An MCP agent gives languagetobrief.createas a string or as a list,["en", "es", "de"], the first being the article.
parts lists the article and each version, and steps the whole plan.
curl -X POST "$BRENZURI_URL/api/v1/briefs/$BRIEF_ID/estimate" \
-H "Authorization: Bearer $BRENZURI_KEY"{
"credits": 3,
"parts": [
{
"label": "Article",
"credits": 1,
"kind": "article"
},
{
"label": "Spanish version",
"credits": 1,
"kind": "version"
},
{
"label": "German version",
"credits": 1,
"kind": "version"
}
],
"steps": [
{
"id": "find",
"name": "Searching your domains",
"estMs": 14200
},
{
"id": "group",
"name": "Grouping by origin",
"estMs": 6100
},
{
"id": "read",
"name": "Reading one page per origin",
"estMs": 39400
},
{
"id": "check",
"name": "Checking claims across origins",
"estMs": 30800
},
{
"id": "write",
"name": "Writing",
"estMs": 48000
},
{
"id": "seo",
"name": "Writing the SEO fields",
"estMs": 4000
},
{
"id": "qa",
"name": "Reading the finished text back",
"estMs": 9000
},
{
"id": "write-es",
"name": "Writing in Spanish",
"estMs": 48000
},
{
"id": "seo-es",
"name": "Writing the SEO fields in Spanish",
"estMs": 4000
},
{
"id": "qa-es",
"name": "Reading the Spanish text back",
"estMs": 9000
},
{
"id": "write-de",
"name": "Writing in German",
"estMs": 48000
},
{
"id": "seo-de",
"name": "Writing the SEO fields in German",
"estMs": 4000
},
{
"id": "qa-de",
"name": "Reading the German text back",
"estMs": 9000
}
],
"enough": true
}POST /articles, as for any brief. The answer lists steps too.
The job #
qa step. Then, for each version in the order of the brief, the job runs its steps:
| Step | What it does |
|---|---|
write-<code> | |
seo-<code> | |
qa-<code> | qa does. |
Versions are independent. One that fails or is skipped has no effect on the others, and none holds the article back: a version that fails or is skipped is left out and the article still finishes. Every language step is optional. A person, or a key with the editscope, can skip one that failed, and a job skips one by itself when it keeps failing, instead of failing the job. Skippingwrite-orqa-leaves that language out; skippingseo-leaves out its SEO fields.The event stream names a skipped step in its summary: skipped, not chargedforwrite-andqa-,skippedforseo-.A version that comes back empty is left out too, and its credit is released. The job takes longer with each version: the planning estimates add about a minute for each. Twenty versions are a long job; follow it, and skip what you do not need.
Credits #
A version that is written and kept is captured with the rest when the job finishes. A version that is skipped, fails or comes back empty is released as unused. One refundedevent withreason: "unused"carries the total just beforedone. It does not end the stream.The job.donewebhook carries the credits captured, not the credits held.A job that fails or is cancelled releases everything it held, as for any job. The briefscope never spends. Estimating a brief with versions is free.
Add a language later #
POST /articles/{id}/languages, or with the article.add_languages tool over MCP. Each is the same action. It needs the generate scope and a role that can edit, and for a key or an agent that is the role of the person who made it.
curl -X POST "$BRENZURI_URL/api/v1/articles/$ARTICLE_ID/languages" \
-H "Authorization: Bearer $BRENZURI_KEY" \
-H "Content-Type: application/json" \
-d '{
"languages": [
"de",
"bhs"
]
}'{
"articleId": "9F3B1C2A-6D4E-4B7A-8C15-2E0A7D91B3F4",
"jobId": "F2D70B6E-1A93-4C85-B0E7-5D49A8C31F62",
"creditsHeld": 2,
"briefId": "5D2E8A14-7B3C-4F69-A0D1-9C46E3B7F208",
"steps": [
{
"id": "sources",
"name": "Reading the sources again",
"estMs": 20000
},
{
"id": "write-de",
"name": "Writing in German",
"estMs": 48000
},
{
"id": "seo-de",
"name": "Writing the SEO fields in German",
"estMs": 4000
},
{
"id": "qa-de",
"name": "Reading the German text back",
"estMs": 9000
},
{
"id": "write-bhs",
"name": "Writing in BHS",
"estMs": 48000
},
{
"id": "seo-bhs",
"name": "Writing the SEO fields in BHS",
"estMs": 4000
},
{
"id": "qa-bhs",
"name": "Reading the BHS text back",
"estMs": 9000
}
]
}The article and its versions are not touched. The job runs sources, then the three steps of each new language.The claims come from the article as it stands, with their states and sources. Nothing is classified again, and a claim a person kept with a note is open in the new version. The pages of the sources are read again through the same hardened fetcher, for the language of the claims and for the read-back. A page that no longer loads is named in the sourcesstep; the read-back runs on the others. If none load, the version is still written and its read-back says it could not run, so the person who reviews it sees the warning.The new versions arrive as articles of their own, needsReview, and each is approved by a person. The first entry of each names the key or the agent that asked.
Add to the article written from the brief. A language version is refused with 422 not_primary.A language that the article already has, its own language, a language twice, one outside the 22, an empty list, or an article whose own language is not one of the 22 is refused with 422 invalid_language.An article that is still being written, or one of whose versions is, or one that already has a job adding languages, is refused with 409 article_generating. An archived article is refused with 409article_archived.While the job runs, the article has addingLanguageswith the job id, so the job can be followed from the article.
Reading the versions #
languageVersions, the article first and then the versions in the order of the table above. It is present only when there are at least two.
[
{
"language": "en",
"articleId": "9F3B1C2A-6D4E-4B7A-8C15-2E0A7D91B3F4",
"status": "approved",
"approved": true
},
{
"language": "es",
"articleId": "1B7E4D90-3C52-4A18-9F6D-C80A2E5B7143",
"status": "needsReview",
"approved": false
}
]GET /articleslists a version as a row of its own, withprimaryArticleId. Group by it, or bylanguageVersionson the article.A version is read, edited, exported and delivered by its own id. The Library and the site desk show a version under the article it belongs to, with its language.
Approval #
A version that is approved and then edited goes back to needsReview, like any article.The review mail names the article and its versions together: “Ferry operators and its Spanish and German versions are ready for review”, with a link for each. A job that adds languages sends one mail for the versions it made. Approving a version raises its own article.approvedwebhook, and delivers that version to the site’s connection as its own draft.
Writing again, archiving and deleting #
Write again on the article writes the article again, and writes the versions the brief names that the article does not have yet. Write again on a version writes that version again, for 1 credit, from the article’s claims. These are a person’s actions in the interface; a key cannot call them. Archiving an article archives all its versions with it, and is refused with 409 article_generatingwhile any of them is being written. Archiving a version archives that version only, and its language can then be added again.At most one version of each language exists for an article. An archived version does not count.
Errors #
| Answer | When |
|---|---|
invalid_language | |
not_primary | |
article_generating | |
article_archived | |
insufficient_credits | |
budget_exhausted |