Когда мы разрабатываем и используем веб-сервисы на платформе 1С, одной из распространенных проблем может стать некорректная локализация данных, таких как даты и строковые представления объектов. Мы сталкиваемся с ситуацией, когда веб-сервис, опубликованный на платформе 1С, отдает данные стороннему сервису, но при этом форматирует их в английской локализации, даже если все настройки 1С и операционной системы на сервере установлены на русский язык. Например, дата может быть представлена как "1/1/2022 11:55:03 PM", а ссылка на документ как "Заявка 00000000341 from 01.01.2022 23:48". Давайте подробно разберем, почему это происходит и как мы можем решить эту проблему.
Прежде всего, давайте выясним причину такого поведения. Как мы отметили в обсуждении, данные из базы 1С получаются запросом, который в консоли запросов или при вызове из внешней обработки возвращает данные в верном (русском) формате. Проблема проявляется исключительно при работе веб-сервиса. Это наводит нас на мысль, что дело не в логике получения данных внутри 1С или в общих настройках локализации базы, а в том, как эти данные сериализуются и передаются через веб-сервис.
Основная причина кроется во взаимодействии веб-сервиса с клиентским приложением, которое к нему обращается (например, Postman, другой веб-сервис или веб-клиент). Платформа 1С:Предприятие, особенно при работе с веб-сервисами (SOAP) и HTTP-сервисами (JSON), может определять язык пользовательского интерфейса и форматирования данных на основе определенных приоритетов. Одним из ключевых факторов, влияющих на это, является HTTP-заголовок Accept-Language, который клиент отправляет в запросе.
Если клиент, обращающийся к нашему веб-сервису, отправляет запрос с заголовком Accept-Language, содержащим английскую локаль (например, en-US, en), то 1С может интерпретировать это и формировать даты, числа и строковые представления ссылок в соответствии с этой локалью. Это происходит еще до того, как данные достигнут клиентского приложения, то есть сам веб-сервис 1С на этапе формирования ответа применяет нужную (с его точки зрения) локализацию.
Мы видим, что, несмотря на русские региональные настройки сервера, настройки языка 1С и пользователя базы, клиентский запрос может влиять на формат выводимых данных. Это как если бы клиент говорит: "Пусть все данные будут на английском", и 1С послушно следует этому указанию.
Для решения описанной проблемы нам необходимо действовать в двух основных направлениях: либо влиять на заголовки клиентского запроса, чтобы 1С изначально формировала данные в нужной нам локали, либо явно форматировать данные внутри 1С в универсальный, машиночитаемый формат, который не зависит от локализации.
Accept-LanguageПервый шаг – проверить, какой заголовок Accept-Language отправляет клиентское приложение. Если мы используем инструмент типа Postman для тестирования веб-сервиса, мы можем легко просмотреть и изменить этот заголовок.
Как проверить в Postman:
Откройте вкладку "Headers" в вашем запросе к веб-сервису. Посмотрите, есть ли там заголовок Accept-Language. Если он присутствует и содержит значения типа en-US, en или другие английские локали, это, скорее всего, и является причиной проблемы.
Как изменить:
Попробуйте явно добавить или изменить заголовок Accept-Language, установив его в ru-RU или просто ru. Например:
Accept-Language: ru-RU, ru;q=0.9, en-US;q=0.8, en;q=0.7 (для приоритета русского языка)Accept-Language: ru (для явного указания русского языка)После изменения заголовка повторите запрос и проверьте, изменился ли формат дат и ссылок в ответе веб-сервиса. Если проблема исчезла, значит, причина была именно в этом заголовке. В таком случае, нам нужно будет обеспечить, чтобы сторонние сервисы, взаимодействующие с нашим веб-сервисом, отправляли соответствующий заголовок.
Независимо от того, можем ли мы влиять на клиентские заголовки, наиболее надежным и рекомендуемым подходом при обмене данными через веб-сервисы является явное форматирование данных в универсальные, машиночитаемые форматы. Это гарантирует, что данные будут интерпретированы одинаково любой стороной, независимо от ее локальных настроек.
Для дат мы настоятельно рекомендуем использовать международный стандарт ISO 8601. Этот формат ("ГГГГ-ММ-ДДTЧЧ:ММ:ССZ", например "2009-02-15T00:00:00Z") является универсальным, машиночитаемым и не зависит от локализации. Он соответствует типу dateTime в схеме XML и поддерживается большинством систем.
В 1С для сериализации дат в такой формат мы можем использовать следующие функции и параметры:
Для XML-сериализации: Функция XMLСтрока()
ДатаИзБазы = ТекущаяДата(); // Предположим, это наша дата из 1С
СтрокаДатыISO = XMLСтрока(ДатаИзБазы);
// Пример: "2023-10-27T10:30:00"
При десериализации можно использовать XMLЗначение().
Для JSON-сериализации: Функция ЗаписатьДатуJSON() с параметром ФорматДатыJSON.ISO или настройка ЗаписьJSONНастройки.
Когда мы работаем с JSON, формат даты не стандартизирован в самом JSON, но 1С предоставляет удобные механизмы для его управления. Используя перечисление ФорматДатыJSON, мы можем указать желаемый формат.
Рассмотрим пример формирования JSON-объекта, содержащего дату в формате ISO:
// Предположим, у нас есть структура данных, которую нужно сериализовать
СтруктураДанных = Новый Структура;
СтруктураДанных.Вставить("ИдентификаторДокумента", "00000000341");
СтруктураДанных.Вставить("ДатаДокумента", ТекущаяДата()); // Дата из базы 1С
СтруктураДанных.Вставить("НаименованиеДокумента", "Заявка");
// Создаем настройки для записи JSON
НастройкиJSON = Новый ЗаписьJSONНастройки;
// Указываем, что даты должны быть в формате ISO
НастройкиJSON.ФорматДатыJSON = ФорматДатыJSON.ISO;
// Также можно указать вариант записи даты (UTC, локальная дата, локальная дата со смещением)
НастройкиJSON.ВариантЗаписиДатыJSON = ВариантЗаписиДатыJSON.ВЛокальнойДате;
// Или ВариантЗаписиДатыJSON.ВUTC, если требуется дата по UTC
// Создаем объект для записи JSON в строку
ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.УстановитьСтроку(НастройкиJSON);
// Сериализуем нашу структуру в JSON
ЗаписатьJSON(ЗаписьJSON, СтруктураДанных);
// Получаем результирующую JSON-строку
СтрокаJSON = ЗаписьJSON.Закрыть();
Сообщить(СтрокаJSON);
// Примерный вывод (зависит от текущей даты):
// {"ИдентификаторДокумента":"00000000341","ДатаДокумента":"2023-10-27T10:30:00","НаименованиеДокумента":"Заявка"}
Такой подход гарантирует, что дата будет передана в виде стандартизированной строки, которую принимающая сторона сможет корректно разобрать, не завися от ее региональных настроек.
Для строковых представлений, таких как "Заявка 00000000341 from 01.01.2022 23:48", мы рекомендуем передавать машиночитаемые идентификаторы и метаданные отдельно, а не пытаться формировать сложную локализованную строку в 1С. Например, вместо одной строки "Заявка 00000000341 from 01.01.2022 23:48" лучше передать:
СтруктураСслылки = Новый Структура;
СтруктураСслылки.Вставить("ТипДокумента", "Заявка");
СтруктураСслылки.Вставить("НомерДокумента", "00000000341");
СтруктураСслылки.Вставить("ДатаДокумента", ДатаДокументаВФорматеISO); // Использовать ISO формат даты
Тогда принимающая сторона сможет сама собрать строку в нужной ей локализации и формате. Если же по каким-то причинам нам все-таки требуется передать строку с фиксированной локалью, мы можем использовать функцию НСтр(), явно указывая язык в форматной строке:
// Получаем номер и дату документа из базы
НомерДокумента = ДокументОбъект.Номер; // Например, "00000000341"
ДатаДокумента = ДокументОбъект.Дата; // Например, 01.01.2022 23:48:00
// Форматируем дату в удобный для отображения вид на русском языке
ФорматированнаяДата = Формат(ДатаДокумента, "ДЛФ=D"); // "01.01.2022"
// Используем НСтр для формирования строки с явным указанием русского языка
СтрокаСсылкиНаРусском = НСтр("ru = 'Заявка %1 от %2'", НомерДокумента, ФорматированнаяДата);
// Результат: "Заявка 00000000341 от 01.01.2022"
Этот подход позволяет нам контролировать локализацию строки на этапе формирования в 1С, но он менее гибок для принимающей стороны, чем передача отдельных полей.
Формат(..., "L=")При форматировании данных в 1С мы должны быть осторожны с использованием параметра L= в функции Формат(), который предназначен для переопределения локализации отображения данных по умолчанию (формат ОС). Если мы не имеем острой необходимости в этом, лучше избегать данного параметра, чтобы не создавать дополнительные сложности при локализации и не зависеть от региональных установок текущего сеанса или ОС.
Хотя основная причина нашей проблемы связана с клиентским заголовком Accept-Language, важно также убедиться, что общие настройки локализации в нашей системе 1С и на сервере корректны. Это поможет избежать других возможных проблем с локализацией:
\L при запуске толстого клиента (например, 1cestart.exe /Lru). Для веб-клиента мы можем добавить /?L=ru или /?L=ru_RU в адресную строку браузера.conf.cfg: В некоторых случаях язык системы может быть задан в файле conf.cfg параметром SystemLanguage.sudo locale-gen ru_RU с последующим выбором русской локали по умолчанию).Однако, еще раз подчеркнем, что эти общие настройки, скорее всего, не являются прямой причиной нашей конкретной проблемы, связанной с влиянием Accept-Language на веб-сервис.
Мы выяснили, что причина того, что веб-сервис 1С возвращает даты и ссылки в английской локализации, вероятнее всего, кроется во влиянии клиентского заголовка Accept-Language. Для решения этой проблемы мы можем либо повлиять на клиент, чтобы он отправлял корректный заголовок (например, Accept-Language: ru), либо, что является более надежным подходом, явно форматировать данные внутри 1С в универсальные, машиночитаемые форматы, такие как ISO 8601 для дат, и передавать отдельные компоненты ссылки вместо одной сложноформатированной строки. Это позволит нам обеспечить консистентность и независимость обмена данными от региональных настроек как на стороне сервера, так и на стороне клиента.