# API за преводи

> Ендпойнтите за преводи връщат всяка езикова версия на запис в един отговор: title или name, overview, tagline и homepage за филми и сериали, name и overview за епизоди. Всеки ред носи iso_639_1, iso_3166_1 и english_name. Ползвайте го, за да четете езици, които параметърът language не обслужва, или за да построите верига от резервни езици.

## Ендпойнт

`GET /3/movie/{movie_id}/translations`

```bash
curl "https://api.amodb.dev/3/movie/550/translations" \
  -H "Authorization: Bearer $AMODB_KEY"
```

Отговор:

```json
{
  "id": 550,
  "translations": [
    {
      "iso_3166_1": "AR",
      "iso_639_1": "ar",
      "name": "العربية",
      "english_name": "Arabic",
      "data": {
        "title": "نادي القتال",
        "overview": "يعيش موظف مكتبي يعاني من الأرق والملل حياة روتينية فارغة، إلى أن يلتقي بالرجل الغامض تايلر ديردن، الذي يختلف عنه تمامًا ويؤمن بأن التحرر من قيود المجتمع يبدأ برفض الحياة التقليدية. تنشأ بينهما صداقة غريبة تقودهما إلى تأسيس نادٍ سري يتجمع في...",
        "homepage": "",
        "tagline": "نادي القتال هو نادي يوجد في العقل الباطن لكل واحد منا !",
        "runtime": 0
      }
    },
    {
      "iso_3166_1": "AZ",
      "iso_639_1": "az",
      "name": "Azərbaycan",
      "english_name": "Azerbaijani",
      "data": {
        "title": "Döyüş Klubu",
        "overview": "Xəyalları olmayan bir gənc yuxusuzluğa qarşı mübarizə aparır, bəlkə də boz və gündəlik həyatı ilə cansıxıcılığının nəticəsidir. Təyyarə gəzintisində o, çox xüsusi bir fəlsəfəyə sahib olan xarizmatik sabun satıcısı Tyler Durden ilə tanış olu...",
        "homepage": "",
        "tagline": "",
        "runtime": 0
      }
    },
    {
      "iso_3166_1": "BY",
      "iso_639_1": "be",
      "name": "Беларуская",
      "english_name": "Belarusian",
      "data": {
        "title": "Байцоўскі клуб",
        "overview": "A ticking-time-bomb insomniac and a slippery soap salesman channel primal male aggression into a shocking new form of therapy. Their concept catches on, with underground \"fight clubs\" forming in every town, until an eccentric gets in the wa...",
        "homepage": "",
        "tagline": "",
        "runtime": 0
      }
    }
  ]
}
```

## Вземане на преводите на филм

`GET /3/movie/{movie_id}/translations` връща по един ред за всеки език, който има текст за филма. Всеки ред съдържа обект `data` с преведените полета. Извикването не приема езиков параметър, защото целта е да видите всички езици наведнъж.

Примерът намира руския ред и отпечатва заглавието му и началото на описанието.

```bash
curl -s "https://api.amodb.dev/3/movie/550/translations" \
  -H "Authorization: Bearer $AMODB_KEY"
```

```js
const url = 'https://api.amodb.dev/3/movie/550/translations';
const res = await fetch(url, { headers: { Authorization: `Bearer ${process.env.AMODB_KEY}` } });
if (!res.ok) throw new Error(`amodb returned ${res.status}`);
const { translations } = await res.json();
const ru = translations.find((t) => t.iso_639_1 === 'ru');
console.log(ru ? `${ru.data.title}: ${ru.data.overview.slice(0, 80)}` : 'no Russian row');
```

```python
import os
import requests

r = requests.get(
    "https://api.amodb.dev/3/movie/550/translations",
    headers={"Authorization": f"Bearer {os.environ['AMODB_KEY']}"},
    timeout=10,
)
r.raise_for_status()
ru = next((t for t in r.json()["translations"] if t["iso_639_1"] == "ru"), None)
print(f"{ru['data']['title']}: {ru['data']['overview'][:80]}" if ru else "no Russian row")
```

```php
<?php
$ch = curl_init('https://api.amodb.dev/3/movie/550/translations');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_TIMEOUT => 10,
    CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('AMODB_KEY')],
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($status !== 200) {
    throw new RuntimeException("amodb returned $status");
}
foreach (json_decode($body, true)['translations'] as $t) {
    if ($t['iso_639_1'] === 'ru') {
        echo $t['data']['title'], ': ', mb_substr($t['data']['overview'], 0, 80), PHP_EOL;
        exit;
    }
}
echo 'no Russian row', PHP_EOL;
```

```go
package main

import (
	"encoding/json"
	"fmt"
	"net/http"
	"os"
	"time"
)

type Translations struct {
	Translations []struct {
		ISO6391 string `json:"iso_639_1"`
		Data    struct {
			Title    string `json:"title"`
			Overview string `json:"overview"`
		} `json:"data"`
	} `json:"translations"`
}

func main() {
	req, _ := http.NewRequest("GET", "https://api.amodb.dev/3/movie/550/translations", nil)
	req.Header.Set("Authorization", "Bearer "+os.Getenv("AMODB_KEY"))
	client := &http.Client{Timeout: 10 * time.Second}
	res, err := client.Do(req)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()
	if res.StatusCode != http.StatusOK {
		panic(res.Status)
	}
	var t Translations
	if err := json.NewDecoder(res.Body).Decode(&t); err != nil {
		panic(err)
	}
	for _, row := range t.Translations {
		if row.ISO6391 == "ru" {
			text := []rune(row.Data.Overview)
			if len(text) > 80 {
				text = text[:80]
			}
			fmt.Printf("%s: %s\n", row.Data.Title, string(text))
			return
		}
	}
	fmt.Println("no Russian row")
}
```

### Параметри

| Параметър  | Къде   | Задължителен  | Описание                                                            |
| ---------- | ------ | ------------- | ------------------------------------------------------------------- |
| `movie_id` | път    | да            | Числов id на филма, например `550`.                                 |
| `api_key`  | заявка | един от двата | Вашият ключ. Ползвайте него или заглавката `Authorization: Bearer`. |

### Полета на отговора

| Поле                          | Тип        | Бележки                                                                                                                                     |
| ----------------------------- | ---------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
| `id`                          | цяло число | Id на филма.                                                                                                                                |
| `translations`                | масив      | По един ред за всеки език с текст, подредени по езиков код. Филм 550 връща 50 реда.                                                         |
| `translations[].iso_3166_1`   | низ        | Държавен код, който върви с езика, като `US` за `en` или `BR` за `pt`. За езици извън 14-те обслужвани повтаря езиковия код с главни букви. |
| `translations[].iso_639_1`    | низ        | Езиков код като `ru` или `pt`. Уникален в масива.                                                                                           |
| `translations[].name`         | низ        | Езикът, записан на самия език.                                                                                                              |
| `translations[].english_name` | низ        | Името на езика на английски.                                                                                                                |
| `translations[].data`         | обект      | Преведените полета. Ключовете зависят от ресурса, вижте таблицата по-долу.                                                                  |

### Примерен отговор

Показани са два от 50-те реда, а описанията са съкратени.

```json
{
  "id": 550,
  "translations": [
    {
      "iso_3166_1": "US",
      "iso_639_1": "en",
      "name": "English",
      "english_name": "English",
      "data": {
        "title": "Fight Club",
        "overview": "A ticking-time-bomb insomniac and a slippery soap salesman channel primal male aggression into a shocking new form of therapy....",
        "homepage": "https://www.20thcenturystudios.com/movies/fight-club",
        "tagline": "Mischief. Mayhem. Soap.",
        "runtime": 0
      }
    },
    {
      "iso_3166_1": "RU",
      "iso_639_1": "ru",
      "name": "Русский",
      "english_name": "Russian",
      "data": {
        "title": "Бойцовский клуб",
        "overview": "Сотрудник страховой компании страдает хронической бессонницей и отчаянно пытается вырваться из мучительно скучной жизни. Однажд...",
        "homepage": "https://www.20thcenturystudios.com/movies/fight-club",
        "tagline": "«Интриги. Хаос. Мыло»",
        "runtime": 0
      }
    }
  ]
}
```

В amodb `runtime` в ред с превод е винаги 0. Четете продължителността от записа с [детайли за филм](https://amodb.dev/bg/movies/).

## Ендпойнти за преводи и техните ключове в data

Всички пътища имат обща основа `https://api.amodb.dev/3`. Всеки връща `id` и масив `translations` с формата на реда по-горе. Променят се само ключовете вътре в `data`.

| Метод и път                                                                        | Ключове в `data`                                                 |
| ---------------------------------------------------------------------------------- | ---------------------------------------------------------------- |
| `GET /movie/{movie_id}/translations`                                               | `title`, `overview`, `homepage`, `tagline`, `runtime` (винаги 0) |
| `GET /tv/{series_id}/translations`                                                 | `name`, `overview`, `homepage`, `tagline`                        |
| `GET /tv/{series_id}/season/{season_number}/translations`                          | няма, масивът винаги е празен                                    |
| `GET /tv/{series_id}/season/{season_number}/episode/{episode_number}/translations` | `name`, `overview`                                               |

Записите за сериали изброяват приблизително толкова езици, колкото филмите. Редовете за епизоди покриват само обслужваните езици, които имат текст за този епизод, от 2 до 14 в проверените извадки. Третирайте липсващ ключ като празна стойност и игнорирайте ключове, които не познавате. Вижте [сериали](https://amodb.dev/bg/tv-series/) за родителските записи.

amodb не предлага преводи за личности и колекции. Биографията на личност следва параметъра `language` на извикването за детайли на личност, а описанието на колекция идва както е записано.

## Резервен вариант, когато липсва текст

Едно заглавие може да съществува на 14 езика и пак да има празно описание на езика, който потребителят е избрал. Минете по верига от езици, вземете първата непразна стойност и запомнете от кой език идва.

```js
function pickText(translations, wanted, field) {
  for (const code of [...wanted, 'en']) {
    const row = translations.find((t) => t.iso_639_1 === code);
    const value = row?.data?.[field];
    if (value) return { code, value };
  }
  return null;
}

// Prefer Ukrainian, then Russian, then English.
// const hit = pickText(translations, ['uk', 'ru'], 'overview');
```

За сериал подайте `'name'` като поле вместо `'title'`. Отбелязвайте в интерфейса текст от резервен език, за да разбира потребителят защо украинска страница показва английско резюме.

## Translations или параметърът language

| Нужда                                                   | Какво да ползвате                           |
| ------------------------------------------------------- | ------------------------------------------- |
| Показване на един език на един потребител               | `language` при извикване за детайли         |
| Изброяване на всички езици на заглавие в редактор       | Този ендпойнт                               |
| Четене на език, който `language` не обслужва, като `ja` | Този ендпойнт, изберете реда по `iso_639_1` |
| Проверка кои от 14-те обслужвани езика имат текст       | Този ендпойнт, сравнете `iso_639_1`         |
| Построяване на връзки към страници на други езици       | Този ендпойнт, четете наличните кодове      |

За таговете, които `language` приема, вижте [езици](https://amodb.dev/bg/languages/). Всеки друг таг при извикване за детайли се заменя с английски.

## Грешки

| HTTP | status_code | Кога                                                                        |
| ---- | ----------- | --------------------------------------------------------------------------- |
| 401  | 7           | Ключът липсва или е грешен.                                                 |
| 402  | 36          | Периодът на плана е изтекъл.                                                |
| 404  | 34          | Няма сезон или епизод с това id, или id не е число.                         |
| 405  | 37          | Ползвали сте метод за запис на път за преводи.                              |
| 429  | 25          | Надхвърлили сте лимита на заявки в минута. Изчакайте `Retry-After` секунди. |

Id на филм или сериал, което не съществува, на този път не е грешка: отговаря със 200 и `"translations": []`, докато пътят за детайли отговаря с 404. Повече на страниците [грешки](https://amodb.dev/bg/errors/) и [лимити на заявките](https://amodb.dev/bg/rate-limits/).

## Практически бележки

- Едно извикване замества до 14 извиквания за детайли. Ползвайте го, когато ви трябват повече от два езика на едно заглавие.
- Редовете са подредени по езиков код, което не е ред на приоритет. Избирайте редове по `iso_639_1`, никога по позиция в масива.
- Извикванията от тип детайли се кешират на edge за 6 часа, така че клиентски кеш със същата дължина не струва нищо в свежест.
- Оригиналните заглавия в други писмености, като японска или корейска, винаги са налични в `original_title` и `original_name` на записа за детайли.
- За да добавите преводи към извикване за детайли, подайте `append_to_response=translations` и четете същия масив от отговора. Работи за филми, сериали и епизоди. Добавеният блок няма `id`.

## Въпроси и отговори

### Кога да ползвам translations вместо параметъра language?

Ползвайте language, когато показвате един език на потребител. Ползвайте translations, когато ви трябват няколко езика на едно заглавие наведнъж, например за екран на редактор, страници на алтернативни езици или проверка на покритието. Той връща и езици, които language не обслужва, като ja или de.

### Каква е разликата между iso_639_1 и iso_3166_1?

iso_639_1 е езиковият код като pt. iso_3166_1 е държавата, която върви с него, като BR. За езици извън 14-те обслужвани той повтаря езиковия код с главни букви, например DA за da, затова винаги съпоставяйте по iso_639_1.

### Защо поле вътре в data е празно?

Празен низ или нула означава, че за това поле на този език няма текст. Не го показвайте. Преминете към следващия език във веригата си, обикновено английски, или към оригиналното заглавие.

### Кои езици покрива ендпойнтът?

Записите за филми и сериали изброяват всеки език, който каталогът държи, често от 40 до 80 реда. Това включва 14-те обслужвани: en, ru, uk, be, zh, pt, bg, he, cs, ro, fr, pl, it и es. Епизодите изброяват само част от тези 14.

## Свързани страници

- [API за детайли на филм](https://amodb.dev/bg/movies/): API за детайли на филм със същите пътища и JSON като TMDB v3. Един филм по id, а актьори, рейтинги и настроения през append_to_response, на 14 езика.
- [API за сериали](https://amodb.dev/bg/tv-series/): API за сериали със същите пътища и JSON като TMDB v3. Сериал по id със сезони, мрежи и следващ епизод, плюс възрастови рейтинги и доставчици за гледане.
- [API за детайли на личност](https://amodb.dev/bg/people/): API за детайли на личност със същите пътища и JSON като TMDB v3. Актьор или член на екип по id с биография, филмография, външни id и списък с популярни.
- [API за колекции](https://amodb.dev/bg/collections/): API за колекции от филми с пътища на TMDB v3: франчайз по id с всичките му части, belongs_to_collection във филм и търсене на колекции по име.
- [Езици](https://amodb.dev/bg/languages/): amodb връща заглавия, описания и имена на 14 езика. Подайте таг в стил TMDB, например ru-RU или pt-BR, в language; всеки друг таг се заменя с английски.
- [Многоезично API за метаданни на филми](https://amodb.dev/bg/multilingual-movie-metadata-api/): Многоезично API за метаданни на филми на 14 езика. Тагове за език на TMDB, всички преводи, резервен английски и правилно показване на иврит отдясно наляво.

Обновено: 2026-10-18. Source: https://amodb.dev/bg/translations/
