Локализация

Max PrilutskiyГенеральный директор и соучредительUpdated в прошлом месяце · 7 min read

У вас есть строка или небольшой объект со строками, который нужно перевести на другой язык прямо сейчас: подпись поля формы, уведомление, короткий фрагмент UI-текста, которого ждёт пользователь. Вам не хочется поднимать endpoint с webhook или опрашивать задачу ради одного ответа. Вам нужно отправить текст и сразу получить перевод.

Именно для этого нужен синхронный endpoint Localize: один запрос — и переведённые данные возвращаются в той же структуре. Вы отправляете контент в формате ключ-значение с исходной и целевой локалью, запрос блокируется, пока ваш движок выполняет перевод, а в ответе приходит тот же объект — с переведёнными значениями и без изменений в структуре. Не нужно отслеживать задачу и делать второй запрос.

Это не просто вызов модели. Запрос проходит через настроенный вами движок локализации — с его глоссарием, тональностью бренда, правилами и выбором модели для каждой локали — тот самый движок, что использует асинхронный API. Разница лишь в форме: асинхронный режим отправляет один запрос сразу в несколько локалей и возвращает результаты по мере готовности; этот вызов работает с одной парой локалей и возвращает результат сразу.

Вам достаточно одной локали и блокирующего вызова? Значит, вы по адресу.

Используйте этот endpoint, когда вам нужна одна пара локалей и вы готовы дождаться одного цикла запрос-ответ. Если у вас много целевых локалей, длинный контент или вам важно изолировать ошибки по каждой локали, async API локализации принимает один запрос, сразу возвращает 202 и запускает каждую локаль как отдельный надёжный фоновый Процесс. Есть и ещё одно отличие, помимо задержки: пайплайн локализации — предредактирование, проверка человеком, обратный перевод и другие необязательные этапы — работает только для асинхронных задач. Этот синхронный вызов игнорирует конфигурацию пайплайна.

На этой странице

Запрос#

text
POST /process/localize

Для аутентификации используйте заголовок X-API-Key. Ключи привязаны к организации и дают доступ ко всем движкам в её рамках — см. Authentication, чтобы узнать, где его сгенерировать, и Errors and status codes для полной модели ошибок.

ПараметрТипОписание
engineIdstring (optional)Идентификатор движка локализации (eng_...). Если не указан, используется движок вашей организации по умолчанию.
sourceLocalestringИсходная локаль BCP-47, например en.
targetLocalestringЦелевая локаль BCP-47, например de.
dataobjectКонтент в формате ключ-значение для перевода. Поддерживаются вложенные объекты и массивы; ответ повторяет ту же структуру, которую вы отправили.
contextstring (optional)Общий контекст для этого набора данных — например, часть продукта, аудитория или цель. Применяется ко всему запросу.
hintsobject (optional)Контекстные подсказки для каждого ключа. Ключи соответствуют ключам data; значения — массивы строк-хлебных крошек (например, { "nav.home": ["Navbar", "Home link"] }), которые показывают движку, где находится строка, чтобы он мог точнее интерпретировать короткий или многозначный текст.
json
{
  "engineId": "eng_abc123",
  "sourceLocale": "en",
  "targetLocale": "de",
  "data": {
    "greeting": "Hello, world!",
    "cta": "Get started"
  },
  "hints": {
    "cta": ["Landing page", "Primary button"]
  }
}

Ответ#

В ответе вы получаете переведённый контент в той же структуре, что и отправили, а также модель, которая выполнила перевод, и стоимость запроса. Возвращаются те же ключи и та же вложенность — ваш код может извлечь перевод из уже знакомой ему структуры.

ПолеТипОписание
sourceLocalestringИсходная локаль BCP-47, возвращённая из запроса.
targetLocalestringЦелевая локаль BCP-47, возвращённая из запроса.
dataobjectПереведённый контент в формате ключ-значение, соответствующий структуре входных данных.
modelstring (optional)LLM model, которая выполнила этот перевод, в формате provider/model (например, anthropic/claude-sonnet-4.5). Это поле показывает, какая именно модель из вашей fallback-цепочки была использована. Отсутствует, если вызова LLM не было — см. примечание ниже.
usageobject (optional)Количество токенов и стоимость запроса в USD. Отсутствует, если вызова LLM не было.

Объект usage детализирует стоимость вызова, чтобы вы могли учитывать расходы без отдельного обращения к биллингу:

ПолеТипОписание
inputTokensnumberОбщее количество входных токенов, использованных во всех чанках.
outputTokensnumberОбщее количество выходных токенов, сгенерированных во всех чанках.
cacheReadTokensnumberВходные токены, полученные из prompt cache провайдера, если модель их сообщает.
cacheWriteTokensnumberВходные токены, записанные в prompt cache провайдера, если модель их сообщает.
llmCostnumberСтоимость upstream-провайдера LLM в USD. 0, если стоимость не была указана.
localizationCostnumberСтоимость Lingo.dev за токены в USD, рассчитанная на основе outputTokens.
costnumberОбщая стоимость запроса в USD (llmCost + localizationCost).
json
{
  "sourceLocale": "en",
  "targetLocale": "de",
  "data": {
    "greeting": "Hallo, Welt!",
    "cta": "Jetzt starten"
  },
  "model": "anthropic/claude-sonnet-4.5",
  "usage": {
    "inputTokens": 2789,
    "outputTokens": 861,
    "cacheReadTokens": 0,
    "cacheWriteTokens": 0,
    "llmCost": 0.02129,
    "localizationCost": 0.001722,
    "cost": 0.023012
  }
}

Когда `model` и `usage` отсутствуют

Если data пуст — то есть переводить нечего, — endpoint завершает работу сразу, без вызова LLM, и в ответе не будет model и usage. Это единственный случай, когда поля стоимости отсутствуют, и причина проста: затрат не было. Нечего переводить — нечего и тарифицировать. Каждый запрос, который действительно запускает перевод, включает оба поля. Считайте их необязательными в вашем парсере, и пустой ввод не станет неожиданностью.

Примеры#

Один и тот же вызов на пяти языках. Для наглядности в каждом примере используется плоский объект; data также принимает вложенные объекты и массивы, а ответ возвращается в той же структуре, которую вы отправили.

javascript
const response = await fetch(
  "https://api.lingo.dev/process/localize",
  {
    method: "POST",
    headers: {
      "X-API-Key": "your_api_key",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      engineId: "eng_abc123",
      sourceLocale: "en",
      targetLocale: "de",
      data: {
        greeting: "Hello, world!",
        cta: "Get started",
      },
    }),
  }
);

const { data } = await response.json();
// { greeting: "Hallo, Welt!", cta: "Jetzt starten" }

Что происходит во время локализации#

За одним POST скрывается целая последовательность шагов, и полезно понимать, каких именно, — потому что именно они делают результат согласованным с остальным локализованным контентом, а не превращают его в разовую догадку модели. Когда запрос попадает в endpoint, движок по порядку применяет всю свою конфигурацию:

  1. Выбор модели — выбирается LLM model с наивысшим приоритетом для этой пары локалей. Модели, заданные для конкретных локалей, имеют приоритет над wildcard-моделями (*). Если основная модель не срабатывает, движок автоматически переходит к следующей по рангу.

  2. Тональность бренда — загружается тональность бренда для целевой локали, а если её нет — используется wildcard-версия.

  3. Правила — загружает все правила, подходящие для целевой локали, в том числе правила с подстановочными символами.

  4. Поиск по глоссарию — входные значения разбиваются на пригодные для поиска чанки, для них создаются эмбеддинги, после чего выполняется поиск по векторному сходству в glossary движка. Найденные термины закрепляют точные переводы или помечают термины как непереводимые, чтобы они проходили без изменений.

  5. Генерация — составленный prompt отправляется в выбранную модель, после чего JSON-ответ разбирается и проходит валидацию.

Это тот же набор шагов движка, который async API выполняет для каждой задачи. Выбор sync вместо async меняет способ доставки результата, а не сам процесс перевода, — поэтому строка, переведённая здесь, и та же строка, переведённая в асинхронной задаче, будут опираться на одни и те же термины глоссария и ту же тональность.

Fallback модели происходит автоматически, а ответ показывает, какая именно модель отработала

Если основная модель не срабатывает, движок пробует следующую в порядке ранжирования. Это происходит прозрачно — структура ответа остаётся одинаковой независимо от того, какая модель выполнила перевод. Единственный признак fallback — поле model в ответе: проверяйте его, если вам нужно точно знать, какая модель из вашей цепочки обработала конкретный запрос.

Следующие шаги#