Какие существуют стратегии, обеспечивающие правильную обработку всех операций с учетом локали во всех локалях? - PullRequest
9 голосов
/ 28 февраля 2012

В некоторой степени по необходимости я разрабатываю программное обеспечение с моим языковым стандартом "C" или "en_US".Трудно использовать другую локаль, потому что я говорю только на одном языке с чем-то, что даже дистанционно приближается к беглости.

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

Чтобы быть более конкретным, я имею в виду ошибки, которые не пропускают текстовые локализации или ошибки в коде для использования этих локализаций.Вместо этого я имею в виду ошибки, в которых языковой стандарт изменяет результат какого-либо API, поддерживающего локали (например, toupper(3)), когда код, использующий этот API, не ожидал возможности такого изменения (например, в турецкой локали * 1010).* не изменяет «i» на «I» - потенциально проблема для сетевого сервера, пытающегося передать определенный сетевой протокол другому хосту).

Вот несколько примеров таких ошибок в программном обеспечении, которые я поддерживаю:

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

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

Другой подход, который мне пришёл в голову, - это использовать (возможно, сначала создать) новую локаль, которая радикально отличается от локали «C», во всех отношениях - иметь другое отображение регистраиспользуйте другой разделитель тысяч, форматируйте даты по-разному и т. д. Этот языковой стандарт можно использовать с одной дополнительной конфигурацией CIS, и мы надеемся, что он будет использоваться для обнаружения любых ошибок в коде, которые могут быть вызваны любым языковым стандартом.

языковой стандарт тестирования уже существует?Есть ли недостатки в этой идее при тестировании на совместимость с локалями?

Какие другие подходы к тестированию локали используют люди?

Меня в первую очередь интересуют локали POSIX, так как это те, которые я знаюоколо.Тем не менее, я знаю, что в Windows также есть некоторые похожие функции, поэтому дополнительная информация (возможно, с дополнительной справочной информацией о том, как эти функции работают), возможно, также будет полезна.

Ответы [ 2 ]

3 голосов
/ 28 февраля 2012

Я бы просто проверил ваш код на предмет некорректного использования таких функций, как toupper. Согласно модели языка C такие функции должны рассматриваться как работающие только с текстом на естественном языке на языке региона. Для любого приложения, которое имеет дело с потенциально многоязычным текстом, это означает, что такие функции, как tolower , вообще не должны использоваться .

Если ваша цель - POSIX, у вас есть немного больше гибкости благодаря функции uselocale, которая позволяет временно переопределять локаль в одном потоке (то есть, не портя глобальное состояние вашей программы). Затем вы можете сохранить языковой стандарт C глобально и использовать tolower и т. Д. Для ASCII / машинно-ориентированного текста (например, файлов конфигурации и т. Д.) И только uselocale для выбранного пользователем языкового стандарта при работе с текстом на естественном языке из указанного языкового стандарта.

В противном случае (и, возможно, даже тогда, когда вам нужно продвинуться дальше), я думаю, что лучшее решение - полностью выбросить такие функции, как tolower и написать свои собственные версии ASCII для текста конфигурации и т. П., И использовать мощный Unicode библиотека для текста на естественном языке.

Единственная проблема, о которой я еще не говорил, - это десятичный разделитель в отношении таких функций, как snprintf и strtod. Изменение его на , вместо . в некоторых локалях может испортить вашу способность анализировать файлы с библиотекой C. Мое предпочтительное решение - просто никогда не устанавливать языковой стандарт LC_NUMERIC. (И я математик, поэтому я склонен полагать, что числа должны быть универсальными, не подпадающими под культурные соглашения.) В зависимости от вашего приложения, единственные действительно языковые категории могут просто быть LC_CTYPE, LC_COLLATE и LC_MESSAGES , Также часто полезными являются LC_MONETARY и LC_TIME.

2 голосов
/ 28 февраля 2012

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

Тестирование вашего собственного кода - я справился с этим, используя 2 или 3 английского языка.настройка локалей в среде CI: en_GB (сопоставление), en_ZW (почти все меняется, но вы все равно можете прочитать ошибки), а затем en_AU (дата, сопоставление)

Если вы хотите убедиться, что ваш код работает смногобайтовые имена файлов, тогда вам также необходимо протестировать с помощью ja_JP

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

PyTZ и PyICU очень полезны при выполнении вышеуказанного.

...