BrenzuriStart free
Write in several languages
Guides

Write in several languages

A language version is written again from the same checked claims, costs 1 credit, and is approved on its own.

On this page

One brief can write an article and any number of language versions of it. A language version is not a translation of the finished text and not a copy: it is written again in its language from the claims the article was already checked against, and it is an article of its own.

What a language version is#

  • It has its own article id, its own versions, its own quality checks and its own label. primaryArticleId on 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#

CodeLanguage
enEnglish
esSpanish
frFrench
deGerman
ptPortuguese
itItalian
nlDutch
plPolish
svSwedish
daDanish
noNorwegian
fiFinnish
csCzech
skSlovak
huHungarian
roRomanian
elGreek
trTurkish
ukUkrainian
jaJapanese
bhsBHS
slSlovenian
  • bhs is 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 receives bs for 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#

Put the article’s language first and the versions after it, joined by +, 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; es and de are 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 422 invalid_language. Codes in a list are lower-cased.
  • An MCP agent gives language to brief.create as a string or as a list, ["en", "es", "de"], the first being the article.

Estimate the brief to see what it costs. 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"
JSON
{
  "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
}
The estimate of the brief above

Start it with POST /articles, as for any brief. The answer lists steps too.

The job#

The article is written first, with its qa step. Then, for each version in the order of the brief, the job runs its steps:

StepWhat it does
write-<code>Writes the article in that language from the claims.
seo-<code>Writes the SEO fields in that language. Only when the brief asks for SEO fields.
qa-<code>Reads the text back against the sources, the way 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 edit scope, can skip one that failed, and a job skips one by itself when it keeps failing, instead of failing the job. Skipping write- or qa- leaves that language out; skipping seo- leaves out its SEO fields.
  • The event stream names a skipped step in its summary: skipped, not charged for write- and qa-, skipped for seo-.
  • 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#

The cost is the article’s, 1 or 2 credits, and 1 more for each language version, whatever the length. All of it is held when the job starts.

  • 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 refunded event with reason: "unused" carries the total just before done. It does not end the stream.
  • The job.done webhook carries the credits captured, not the credits held.
  • A job that fails or is cancelled releases everything it held, as for any job.
  • The brief scope never spends. Estimating a brief with versions is free.

Add a language later#

An article that is finished can get language versions afterwards, from the Add a language action on its page, with 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"
    ]
  }'
JSON
{
  "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 answer: a started job. Credits held: 1 for each language
  1. The article and its versions are not touched. The job runs sources, then the three steps of each new language.
  2. 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.
  3. 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 sources step; 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.
  4. 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 409 article_archived.
  • While the job runs, the article has addingLanguages with the job id, so the job can be followed from the article.

Reading the versions#

The article, and each version, lists them all in 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.

JSON
[
  {
    "language": "en",
    "articleId": "9F3B1C2A-6D4E-4B7A-8C15-2E0A7D91B3F4",
    "status": "approved",
    "approved": true
  },
  {
    "language": "es",
    "articleId": "1B7E4D90-3C52-4A18-9F6D-C80A2E5B7143",
    "status": "needsReview",
    "approved": false
  }
]
languageVersions on an article with one version
  • GET /articles lists a version as a row of its own, with primaryArticleId. Group by it, or by languageVersions on 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.approved webhook, 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_generating while 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#

AnswerWhen
422 invalid_languageA language that is not supported, repeated, empty or equal to the article’s, in a brief or when adding.
422 not_primaryAdding languages to a language version.
409 article_generatingThe article, one of its versions or a job that adds languages is still running.
409 article_archivedThe article is archived.
402 insufficient_creditsThe whole cost, versions included, is not covered.
429 budget_exhaustedThe cost would pass the daily cap of a key or an agent.