# Интернационализация

> Поддержка интернационализации не является необязательной. Она должна быть основной функцией.
>
> * [Яннис Лейдель, выступая на Django Under the Hood, 2015](https://youtu.be/Wa0VfS2q94Y).

DRF поставляется с переводимыми сообщениями об ошибках. Вы можете сделать так, чтобы они отображались на вашем языке, используя [стандартные механизмы перевода Django](https://docs.djangoproject.com/en/stable/topics/i18n/translation).

Это позволит вам:

* Выбрать язык по умолчанию, отличный от английского, используя стандартную настройку Django `LANGUAGE_CODE`.
* Позволить клиентам самим выбирать язык, используя `LocaleMiddleware`, включенный в Django. Типичное использование для клиентов API - включение заголовка запроса `Accept-Language`.

## Включение интернационализированных API

Вы можете изменить язык по умолчанию с помощью стандартной настройки Django `LANGUAGE_CODE`:

```python
LANGUAGE_CODE = "es-es"
```

Вы можете включить языковые запросы на каждый запрос, добавив `LocaleMiddleware` в настройку `MIDDLEWARE`:

```python
MIDDLEWARE = [
    ...
    'django.middleware.locale.LocaleMiddleware'
]
```

Когда интернационализация по каждому запросу включена, клиентские запросы будут учитывать заголовок `Accept-Language`, где это возможно. Например, давайте сделаем запрос для неподдерживаемого типа медиа:

**Запрос**

```http
GET /api/users HTTP/1.1
Accept: application/xml
Accept-Language: es-es
Host: example.org
```

**Ответ**

```http
HTTP/1.0 406 NOT ACCEPTABLE

{"detail": "No se ha podido satisfacer la solicitud de cabecera de Accept."}
```

DRF включает эти встроенные переводы как для стандартных случаев исключений, так и для ошибок валидации сериализатора.

Обратите внимание, что переводы относятся только к самим строкам ошибок. Формат сообщений об ошибках и ключи имен полей останутся неизменными. Пример тела ответа `400 Bad Request` может выглядеть следующим образом:

```http
{"detail": {"username": ["Esse campo deve ser único."]}}
```

Если вы хотите использовать разные строки для таких частей ответа, как `detail` и `non_field_errors`, вы можете изменить это поведение, используя [пользовательский обработчик исключений](https://ilyachch.gitbook.io/django-rest-framework-russian-documentation/overview/navigaciya-po-api/exceptions#пользовательская-обработка-исключений).

#### Указание набора поддерживаемых языков.

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

Если вы хотите поддерживать только часть доступных языков, используйте стандартную настройку Django `LANGUAGES`:

```python
LANGUAGES = [
    ('de', _('German')),
    ('en', _('English')),
]
```

## Добавление новых переводов

Управление переводами DRF осуществляется в режиме онлайн с помощью [Transifex](https://www.transifex.com/projects/p/django-rest-framework/). Вы можете использовать сервис Transifex для добавления новых языков перевода. Команда сопровождения обеспечит включение этих строк перевода в пакет DRF.

Иногда вам может понадобиться добавить строки перевода в ваш проект локально. Это может понадобиться, если:

* Вы хотите использовать DRF на языке, который еще не переведен на Transifex.
* Ваш проект включает пользовательские сообщения об ошибках, которые не входят в строки перевода DRF по умолчанию.

#### Локальный перевод на новый язык

Это руководство предполагает, что вы уже знакомы с тем, как перевести приложение Django. Если это не так, начните с чтения [Django's translation docs](https://docs.djangoproject.com/en/stable/topics/i18n/translation).

Если вы делаете перевод на новый язык, вам нужно будет перевести существующие сообщения об ошибках DRF:

1. Создайте новую папку, в которой вы хотите хранить ресурсы интернационализации. Добавьте этот путь в настройку [`LOCALE_PATHS`](https://docs.djangoproject.com/en/stable/ref/settings/#std:setting-LOCALE_PATHS).
2. Теперь создайте подпапку для языка, на который вы хотите перевести. Папка должна быть названа с использованием нотации [имя локали](https://docs.djangoproject.com/en/stable/topics/i18n/#term-locale-name). Например: `de`, `pt_BR`, `es_AR`.
3. Теперь скопируйте файл [base translations file](https://raw.githubusercontent.com/encode/django-rest-framework/master/rest_framework/locale/en_US/LC_MESSAGES/django.po) из исходного кода DRF в папку translations.
4. Отредактируйте только что скопированный файл `django.po`, переведя все сообщения об ошибках.
5. Запустите `manage.py compilemessages -l pt_BR`, чтобы сделать переводы доступными для использования Django. Вы должны увидеть сообщение типа `processing file django.po in <...>/locale/pt_BR/LC_MESSAGES`.
6. Перезапустите ваш сервер разработки, чтобы увидеть, что изменения вступили в силу.

Если вы переводите только пользовательские сообщения об ошибках, которые существуют в кодовой базе вашего проекта, вам не нужно копировать исходный файл DRF `django.po` в папку `LOCALE_PATHS`, а можно просто запустить стандартный процесс Django `makemessages`.

## Как определяется язык

Если вы хотите разрешить языковые предпочтения для каждого запроса, вам нужно включить `django.middleware.locale.LocaleMiddleware` в настройку `MIDDLEWARE`.

Более подробную информацию о том, как определяется предпочтение языка, вы можете найти в [документации Django](https://docs.djangoproject.com/en/stable/topics/i18n/translation/#how-django-discovers-language-preference). Для справки, метод следующий:

1. Во-первых, он ищет префикс языка в запрашиваемом URL.
2. Если это не удается, он ищет ключ `LANGUAGE_SESSION_KEY` в текущей сессии пользователя.
3. Если это не удается, выполняется поиск cookie.
4. Если это не удается, просматривается HTTP-заголовок `Accept-Language`.
5. Если это не удается, используется глобальная настройка `LANGUAGE_CODE`.

Для клиентов API наиболее подходящим из них обычно является использование заголовка `Accept-Language`; сеансы и cookies будут недоступны, если не используется аутентификация сеанса, и вообще лучше предпочесть заголовок `Accept-Language` для клиентов API, а не использовать языковые префиксы URL.
