BYO Lite is in beta and enabled per organization. Details can change before general availability.
Prerequisites
- BYO Lite is enabled for your organization. It is in beta.
- An engine with its own HTTP API, and its URL and credentials, such as an API key.
- For a custom template, a JSON template that you wrote, or one you adapted from the pre-built template.
Quickstart
To connect an OpenAI-compatible service with the pre-built template:- In the engine settings, set Engine API to Pre-built template.
- Enter the engine URL, for example
https://api.openai.com, and your credentials. - Optionally add metadata (Custom labels) such as
model, see Metadata in a template. - Save the engine.
Ways to connect
In the engine settings, Engine API offers three options:
Phrase validates the template before the engine is saved.
Template structure
A template is a single JSON file of up to 8 KB. Keys that are not listed here are rejected. A template needs only three blocks:
Each
request and response value is a JSONata expression. A request expression builds the request body of your engine from the variables Phrase provides. A response expression reads the translated text out of the engine’s response. For translate, it must return one translated string per segment, in the same order. Wrap a single value in [...] so that one segment still produces a list.
maxSegments is the highest number of segments your engine accepts in one call. If Phrase has more, it splits them into several calls and joins the results in the original order, so the template only ever describes one call.
Every path in a template (translate, status, languages and the asynchronous blocks) is added to the engine URL you enter in the engine settings. With the engine URL https://api.example.com and the path /v1/translate, Phrase calls https://api.example.com/v1/translate. If the engine URL already ends with a path, such as https://gateway.example.com/openai, the template path is added after it. Repeated slashes are merged, so it doesn’t matter whether either side has a slash at the junction.
The following example shows every block:
- In
translateAsyncStatusandtranslateAsyncResult,{jobId}in the path is replaced with the job ID returned bytranslateAsync. ThedoneWhenandfailedWhenexpressions are evaluated against the status response. While neither matches, Phrase keeps polling.detailis evaluated only whenfailedWhenmatches, and becomes the failure message. Both blocks can also have arequest, which is optional. Without it, the call has no body, so aGETpoll doesn’t need one. headersaccepts up to 10 headers with values of up to 256 characters.Authorization,Host,Content-Type,Content-Length,CookieandX-Phrase-Action-Idcan’t be set, because Phrase manages them.- The
$evaland$errorfunctions are not allowed.
Supported languages in a template
Thelanguages block has two modes.
static lists the languages in the template. Use either pairs, a list of { "sourceLanguage", "targetLanguage" } objects, or codes, a flat list of language codes. Phrase combines the codes into all pairs, leaving out same-to-same pairs. You can also add codesFrom, a JSONata expression evaluated against the metadata. When it returns at least one valid language code, or a comma-separated string of codes, those codes replace pairs or codes. This lets you restrict the languages per engine without editing the template.
pairs when your engine doesn’t support every combination, for example when it translates only from English, or only into some languages. Phrase offers exactly the pairs you list, in that direction only:
endpoint asks your engine. Phrase calls path with method, and response turns the answer into a list of { "sourceLanguage", "targetLanguage" } pairs. If your engine returns only a flat list of codes, set crossProduct to true and let response return that list. Phrase then builds the pairs itself.
Use Phrase locale codes in pairs, codes and codesFrom, for example pt-br. If your engine uses other codes, add them to languageMap and convert in the expressions with $langOut(code) for outgoing codes, and $langIn(code) for incoming ones. A code that is not in the map is converted to a plain upper-case (outgoing) or lower-case (incoming) form.
Variables
These variables are available inrequest expressions:
response, doneWhen, failedWhen, detail, okWhen and error expressions are evaluated against the engine’s response body and have no other variables.
On top of the standard JSONata functions, these functions are available: $langOut and $langIn for language codes, and $fromJson(text), which parses JSON out of a text. $fromJson is meant for language models, which often wrap their answer in a markdown code block or add a sentence before it. If the text is not pure JSON, it uses the last JSON object it finds.
Glossary. For each request, Phrase searches the term bases attached to the job and puts the entries that match the segments of that request into $glossary, without duplicates. If your engine supports glossaries, map them in the request. For a language model, list them in the prompt:
Metadata in a template
Metadata is a set of custom key/value pairs that you add to the engine. In the Phrase UI they are called Custom labels, and in the OpenAPI schema they are themetadata object. A template reads them from $meta, for example $meta.model. The placeholders from Dynamic metadata are resolved before the template runs. Values you enter as Custom labels are text, so convert them in the template when you need a number. A key that is not set has no value, so check it before you use it.
The pre-built template reads these keys:
Custom instructions. Set
custom_instructions to add your own rules to every translation, such as tone of voice, terminology or style. The text is added to the prompt after the built-in translation rules. It applies to every request of the engine, so use a separate engine for rules that differ between projects. The placeholders from Dynamic metadata work here too, but they insert only an ID, not project-specific text. There is no fixed length limit. The text is sent with every request, so it counts against the context size and cost of your model, and you should keep it short.
model to the name of any model your endpoint offers. Without it, the pre-built template uses gpt-4.1-mini. The template sends temperature 0 by default. It leaves it out for model names that contain claude, because those models reject it. A temperature you set always wins.
Languages. Set languages to a comma-separated list of Phrase locale codes, such as en,de,fr, to limit the languages the engine offers. Phrase combines them into all pairs. Without it, the pre-built template offers its built-in list of languages. At most 100 codes are used, and unknown codes are ignored.
Pre-built template
The pre-built template connects to OpenAI and to other services that implement the OpenAI chat completions API. Set the engine URL to the base URL of the service, for examplehttps://api.openai.com. The template:
- calls
POST /v1/chat/completionswith up to 50 segments per request, and checks health withGET /v1/models; - asks the model to translate the segments, to keep inline tags and to return JSON, and adds your glossary and
custom_instructions; - reads the translations from the first answer of the model, even when it is wrapped in a markdown code block;
- reads the error message from the
errorobject of the response; - sends a static
anthropic-versionheader (2023-06-01). If your service doesn’t need it, remove theheadersblock from your copy of the template.
openai-compatible template
Download the template that Phrase uses for OpenAI-compatible engines.
Troubleshooting
Next steps
- Read the BYO Engine guide if you need the full adapter.
- Look up the expression syntax in the JSONata documentation.
- Start from the pre-built template and adapt it.