Почему веб-сервис 1С возвращает даты и ссылки в английской локализации, несмотря на русские настройки?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

Когда мы разрабатываем и используем веб-сервисы на платформе 1С, одной из распространенных проблем может стать некорректная локализация данных, таких как даты и строковые представления объектов. Мы сталкиваемся с ситуацией, когда веб-сервис, опубликованный на платформе 1С, отдает данные стороннему сервису, но при этом форматирует их в английской локализации, даже если все настройки 1С и операционной системы на сервере установлены на русский язык. Например, дата может быть представлена как "1/1/2022 11:55:03 PM", а ссылка на документ как "Заявка 00000000341 from 01.01.2022 23:48". Давайте подробно разберем, почему это происходит и как мы можем решить эту проблему.

Анализ проблемы: почему 1С меняет локализацию?

Прежде всего, давайте выясним причину такого поведения. Как мы отметили в обсуждении, данные из базы 1С получаются запросом, который в консоли запросов или при вызове из внешней обработки возвращает данные в верном (русском) формате. Проблема проявляется исключительно при работе веб-сервиса. Это наводит нас на мысль, что дело не в логике получения данных внутри 1С или в общих настройках локализации базы, а в том, как эти данные сериализуются и передаются через веб-сервис.

Основная причина кроется во взаимодействии веб-сервиса с клиентским приложением, которое к нему обращается (например, Postman, другой веб-сервис или веб-клиент). Платформа 1С:Предприятие, особенно при работе с веб-сервисами (SOAP) и HTTP-сервисами (JSON), может определять язык пользовательского интерфейса и форматирования данных на основе определенных приоритетов. Одним из ключевых факторов, влияющих на это, является HTTP-заголовок Accept-Language, который клиент отправляет в запросе.

Если клиент, обращающийся к нашему веб-сервису, отправляет запрос с заголовком Accept-Language, содержащим английскую локаль (например, en-US, en), то 1С может интерпретировать это и формировать даты, числа и строковые представления ссылок в соответствии с этой локалью. Это происходит еще до того, как данные достигнут клиентского приложения, то есть сам веб-сервис 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 (для явного указания русского языка)

    После изменения заголовка повторите запрос и проверьте, изменился ли формат дат и ссылок в ответе веб-сервиса. Если проблема исчезла, значит, причина была именно в этом заголовке. В таком случае, нам нужно будет обеспечить, чтобы сторонние сервисы, взаимодействующие с нашим веб-сервисом, отправляли соответствующий заголовок.

  2. Явное форматирование данных в 1С

    Независимо от того, можем ли мы влиять на клиентские заголовки, наиболее надежным и рекомендуемым подходом при обмене данными через веб-сервисы является явное форматирование данных в универсальные, машиночитаемые форматы. Это гарантирует, что данные будут интерпретированы одинаково любой стороной, независимо от ее локальных настроек.

    Форматирование дат

    Для дат мы настоятельно рекомендуем использовать международный стандарт 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= в функции Формат(), который предназначен для переопределения локализации отображения данных по умолчанию (формат ОС). Если мы не имеем острой необходимости в этом, лучше избегать данного параметра, чтобы не создавать дополнительные сложности при локализации и не зависеть от региональных установок текущего сеанса или ОС.

  3. Дополнительные настройки локализации в 1С и на веб-сервере (в контексте)

    Хотя основная причина нашей проблемы связана с клиентским заголовком Accept-Language, важно также убедиться, что общие настройки локализации в нашей системе 1С и на сервере корректны. Это поможет избежать других возможных проблем с локализацией:

    1. Параметры запуска 1С: Язык платформы 1С может быть задан с помощью параметра \L при запуске толстого клиента (например, 1cestart.exe /Lru). Для веб-клиента мы можем добавить /?L=ru или /?L=ru_RU в адресную строку браузера.
    2. Файл conf.cfg: В некоторых случаях язык системы может быть задан в файле conf.cfg параметром SystemLanguage.
    3. Региональные настройки пользователя БД и ИБ: В настройках пользователя в 1С можно установить язык интерфейса. При создании или редактировании информационной базы также задаются региональные параметры. Мы уже убедились, что в нашем случае эти настройки русские, но это важный аспект общей картины.
    4. Веб-сервер (IIS/Apache) и системные локали: Несмотря на то что локализация в основном определяется 1С, региональные настройки самого веб-сервера также могут влиять на некоторые аспекты работы или логирование. Для Linux-серверов с Apache может потребоваться настройка системных локалей (например, sudo locale-gen ru_RU с последующим выбором русской локали по умолчанию).
    5. "Использовать региональные установки текущего сеанса": Для веб-клиента, если форматы чисел и дат "плывут", мы можем попробовать снять флаг "Использовать региональные установки текущего сеанса" в региональных настройках базы.

    Однако, еще раз подчеркнем, что эти общие настройки, скорее всего, не являются прямой причиной нашей конкретной проблемы, связанной с влиянием Accept-Language на веб-сервис.

Заключение

Мы выяснили, что причина того, что веб-сервис 1С возвращает даты и ссылки в английской локализации, вероятнее всего, кроется во влиянии клиентского заголовка Accept-Language. Для решения этой проблемы мы можем либо повлиять на клиент, чтобы он отправлял корректный заголовок (например, Accept-Language: ru), либо, что является более надежным подходом, явно форматировать данные внутри 1С в универсальные, машиночитаемые форматы, такие как ISO 8601 для дат, и передавать отдельные компоненты ссылки вместо одной сложноформатированной строки. Это позволит нам обеспечить консистентность и независимость обмена данными от региональных настроек как на стороне сервера, так и на стороне клиента.

← На главную