Как проверить приложение на правильную кодировку (например, UTF-8) - PullRequest
16 голосов
/ 25 января 2009

Проблемы с кодированием относятся к одной из тем, которая чаще всего укусила меня во время разработки. Каждая платформа настаивает на своей собственной кодировке, скорее всего, в игре есть некоторые не-UTF-8 значения по умолчанию. (Я обычно работаю в Linux, по умолчанию UTF-8, мои коллеги в основном работают в немецкой Windows, по умолчанию в ISO-8859-1 или какой-то подобной кодовой странице Windows)

Я полагаю, что UTF-8 является подходящим стандартом для разработки приложений i18nable. Однако, по моему опыту, ошибки кодирования обычно обнаруживаются поздно (хотя я нахожусь в Германии, и у нас есть некоторые специальные символы, которые наряду с ISO-8859-1 обеспечивают некоторые обнаруживаемые различия).

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

Какую [технику | инструмент | стимул] используют здесь люди? Как вы заставляете своих соавторов заботиться об этих проблемах? Как вы проверяете на соответствие? Эти тесты проводятся вручную или автоматически?

Добавление одного возможного ответа заранее:

Я недавно обнаружил fliptitle.com (они предоставляют простой способ получить странные символы, написанные "uʍop ǝpısdn" *), и я планирую использовать их для обеспечения легко проверяемого UTF-8 символьные строки (так как большинство используемых символов находятся в какой-то странной позиции двоичного кодирования), но, безусловно, должны быть более систематические тесты, шаблоны или методы для обеспечения совместимости / использования UTF-8.

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

Спасибо за ваш вклад.

*) это написано "вверх ногами", написано "вверх ногами" для тех, кто не видит эти символы из-за проблем со шрифтом

Ответы [ 5 ]

11 голосов
/ 01 апреля 2010

Спасибо за флиптитл !

Я тоже пытаюсь составить правильный план тестирования, чтобы убедиться, что приложение поддерживает строки Unicode во всей системе.

Я двуязычный, но на двух языках, которые используют только ISO-8859-1. Поэтому я изо всех сил пытался определить, что такое «реальный», «значимый» способ проверить весь спектр возможностей Unicode.

Я только что сталкивался с этим:


Последующее сообщение:

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

Я использую следующие международные строки в своем тесте:

(ПРИМЕЧАНИЕ: вот вам текст в кодировке UTF-8 ... надеюсь, вы увидите это в своем браузере)

ユ ー ザ ー 別 サ イ ト
简体 中文
10 플랫폼 으로
מדורים מבוקשים
أفضل البحوث
Σὲ γνωρίζω ἀπὸ
Десятую Международную
แผ่นดิน ฮั่น เสื่อมโทรม แสน สังเวช
∮ E⋅da = Q, n → ∞, ∑ f (i) = ∏ g (i)
Français Langue étrangère
mañana olé

(Конец UTF-8 иностранного / неанглийского текста)

Однако в разные моменты тестирования я понял, что недостаточно иметь только информацию о том, как должны выглядеть строки при визуализации в соответствующих иностранных алфавитах. Мне также нужно было знать правильные номера кодов Unicode, а также правильные шестнадцатеричные значения для этих строк как минимум в двух кодировках (UCS-2 и UTF-8).

Вот эквивалентная нумерация кодов и шестнадцатеричные значения:

str = L"\u30E6\u30FC\u30B6\u30FC\u5225\u30B5\u30A4\u30C8"; // JAPAN 
// Little endian UTF-16/UCS-2: e6 30 fc 30 b6 30 fc 30 25 52 b5 30 a4 30 c8 30 00 00
// Hex of UTF-8: e3 83 a6 e3 83 bc e3 82 b6 e3 83 bc e5 88 a5 e3 82 b5 e3 82 a4 e3 83 88 00 

str = L"\u7B80\u4F53\u4E2D\u6587"; // CHINA 
// Little endian UTF-16/UCS-2: 80 7b 53 4f 2d 4e 87 65 00 00 
// Hex of UTF-8: e7 ae 80 e4 bd 93 e4 b8 ad e6 96 87 00

str = L"\uD06C\uB85C\uC2A4 \uD50C\uB7AB\uD3FC\uC73C\uB85C"; // KOREA 
// Little endian UTF-16/UCS-2: 6c d0 5c b8 a4 c2 20 00 0c d5 ab b7 fc d3 3c c7 5c b8 00 00
// Hex of UTF-8: ed 81 ac eb a1 9c ec 8a a4 20 ed 94 8c eb 9e ab ed 8f bc ec 9c bc eb a1 9c 00 

str = L"\u05DE\u05D3\u05D5\u05E8\u05D9\u05DD \u05DE\u05D1\u05D5\u05E7\u05E9\u05D9\u05DD"; // ISRAEL 
// Little endian UTF-16/UCS-2: de 05 d3 05 d5 05 e8 05 d9 05 dd 05 20 00 de 05 d1 05 d5 05 e7 05 e9 05 d9 05 dd 05 00 00
// Hex of UTF-8: d7 9e d7 93 d7 95 d7 a8 d7 99 d7 9d 20 d7 9e d7 91 d7 95 d7 a7 d7 a9 d7 99 d7 9d 00

str = L"\u0623\u0641\u0636\u0644 \u0627\u0644\u0628\u062D\u0648\u062B"; // EGYPT 
// Little endian UTF-16/UCS-2: 23 06 41 06 36 06 44 06 20 00 27 06 44 06 28 06 2d 06 48 06 2b 06 00 00
// Hex of UTF-8: d8 a3 d9 81 d8 b6 d9 84 20 d8 a7 d9 84 d8 a8 d8 ad d9 88 d8 ab 00 

str = L"\u03A3\u1F72 \u03B3\u03BD\u03C9\u03C1\u03AF\u03B6\u03C9 \u1F00\u03C0\u1F78"; // GREECE 
// Little endian UTF-16/UCS-2: a3 03 72 1f 20 00 b3 03 bd 03 c9 03 c1 03 af 03 b6 03 c9 03 20 00 00
// Hex of UTF-8: ce a3 e1 bd b2 20 ce b3 ce bd cf 89 cf 81 ce af ce b6 cf 89 20 e1 bc 80 cf 80 e1 bd b8 00 

str = L"\u0414\u0435\u0441\u044F\u0442\u0443\u044E \u041C\u0435\u0436\u0434\u0443\u043D\u0430\u0440\u043E\u0434\u043D\u0443\u044E"; // RUSSIA 
// Little endian UTF-16/UCS-2: 14 04 35 04 41 04 4f 04 42 04 43 04 4e 04 20 00 1c 04 35 04 36 04 34 04 43 04 3d 04 30 04 40 04 3e 04 34 04 3d 04 43 04 4e 04 00 00
// Hex of UTF-8: d0 94 d0 b5 d1 81 d1 8f d1 82 d1 83 d1 8e 20 d0 9c d0 b5 d0 b6 d0 b4 d1 83 d0 bd d0 b0 d1 80 d0 be d0 b4 d0 bd d1 83 d1 8e 00

str = L"\u0E41\u0E1C\u0E48\u0E19\u0E14\u0E34\u0E19\u0E2E\u0E31\u0E48\u0E19\u0E40\u0E2A\u0E37\u0E48\u0E2D\u0E21\u0E42\u0E17\u0E23\u0E21\u0E41\u0E2A\u0E19\u0E2A\u0E31\u0E07\u0E40\u0E27\u0E0A"; // THAILAND
// Little endian UTF-16/UCS-2: 41 0e 1c 0e 48 0e 19 0e 14 0e 34 0e 19 0e 2e 0e 31 0e 48 0e 19 0e 40 0e 2a 0e 37 0e 48 0e 2d 0e 21 0e 42 0e 17 0e 23 0e 21 0e 41 0e 2a 0e 19 0e 2a 0e 31 0e 07 0e 40 0e 27 0e 0a 0e 00 00
// Hex of UTF-8: e0 b9 81 e0 b8 9c e0 b9 88 e0 b8 99 e0 b8 94 e0 b8 b4 e0 b8 99 e0 b8 ae e0 b8 b1 e0 b9 88 e0 b8 99 e0 b9 80 e0 b8 aa e0 b8 b7 e0 b9 88 e0 b8 ad e0 b8 a1 e0 b9 82 e0 b8 97 e0 b8 a3 e0 b8 a1 e0 b9 81 e0 b8 aa e0 b8 99 e0 b8 aa e0 b8 b1 e0 b8 87 e0 b9 80 e0 b8 a7 e0 b8 8a 00

str = L"\u222E E\u22C5da = Q,  n \u2192 \u221E, \u2211 f(i) = \u220F g(i)"; // MATHEMATICS 
// Little endian UTF-16/UCS-2: 2e 22 20 00 45 00 c5 22 64 00 61 00 20 00 3d 00 20 00 51 00 2c 00 20 00 20 00 6e 00 20 00 92 21 20 00 1e 22 2c 00 20 00 11 22 20 00 66 00 28 00 69 00 29 00 20 00 3d 00 20 00 0f 22 20 00 67 00 28 00 69 00 29 00 00 00
// Hex of UTF-8: e2 88 ae 20 45 e2 8b 85 64 61 20 3d 20 51 2c 20 20 6e 20 e2 86 92 20 e2 88 9e 2c 20 e2 88 91 20 66 28 69 29 20 3d 20 e2 88 8f 20 67 28 69 29 00 

str = L"fran\u00E7ais langue \u00E9trang\u00E8re"; // FRANCE
// Little endian UTF-16/UCS-2: 66 00 72 00 61 00 6e 00 e7 00 61 00 69 00 73 00 20 00 6c 00 61 00 6e 00 67 00 75 00 65 00 20 00 e9 00 74 00 72 00 61 00 6e 00 67 00 e8 00 72 00 65 00 00 00
// Hex of UTF-8: 66 72 61 6e c3 a7 61 69 73 20 6c 61 6e 67 75 65 20 c3 a9 74 72 61 6e 67 c3 a8 72 65 00

str = L"ma\u00F1ana ol\u00E9"; // SPAIN
// Little endian UTF-16/UCS-2: 6d 00 61 00 f1 00 61 00 6e 00 61 00 20 00 6f 00 6c 00 e9 00 00 00
// Hex of UTF-8: 6d 61 c3 b1 61 6e 61 20 6f 6c c3 a9 00

Кроме того, вот пара изображений, которые показывают некоторые распространенные «неправильные визуализации», которые могут происходить в различных редакторах, даже если нижележащие байты имеют правильную форму UTF8. Если вы видите какую-либо из этих визуализаций, это, вероятно, означает, что вы правильно сгенерировали строку UTF8, но ваш редактор / зритель пытается интерпретировать их в некоторой кодировке, отличной от UTF8.

Образцы визуализации Num. 1

Образцы визуализации Num. 2

6 голосов
/ 25 января 2009

Существует регулярное выражение для проверки правильности строки UTF-8 :

$field =~
  m/\A(
     [\x09\x0A\x0D\x20-\x7E]            # ASCII
   | [\xC2-\xDF][\x80-\xBF]             # non-overlong 2-byte
   |  \xE0[\xA0-\xBF][\x80-\xBF]        # excluding overlongs
   | [\xE1-\xEC\xEE\xEF][\x80-\xBF]{2}  # straight 3-byte
   |  \xED[\x80-\x9F][\x80-\xBF]        # excluding surrogates
   |  \xF0[\x90-\xBF][\x80-\xBF]{2}     # planes 1-3
   | [\xF1-\xF3][\x80-\xBF]{3}          # planes 4-15
   |  \xF4[\x80-\x8F][\x80-\xBF]{2}     # plane 16
  )*\z/x;

Но это не гарантирует, что фактическим текстом является UTF-8.

Пример: Последовательность байтов для буквы ö (U + 00F6) и соответствующей последовательности UTF-8 равна 0xC3B6.
Поэтому, когда вы получаете 0xC3B6 в качестве входных данных, вы можете сказать, что это действительно UTF-8. Но вы не можете с уверенностью сказать, что письмо ö отправлено.
Это потому, что представьте, что был использован не UTF-8, а ISO 8859-1. Там последовательность 0xC3B6 представляет символ Ã (0xC3) и ¶ (0xB6) соответственно.
Таким образом, последовательность 0xC3B6 может представлять собой как с использованием UTF-8, так и с использованием ISO 8859-1 (хотя последнее довольно необычно).

Итак, в конце концов, это только догадки.

3 голосов
/ 26 января 2009

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

Цель, как всегда, состоит в том, чтобы правильно обращаться с ним в каждом отдельном месте. Таким образом, в большинстве случаев простые модульные тесты могут сделать свое дело, это даже не должно быть очень сложным набором символов. Я выявляю все ошибки, просто проверяя наш национальный символ "ø", потому что он отображается по-разному в UTF-8 и большинстве других наборов символов.

Агрегат работает нормально, когда все части делают это правильно. Я знаю, это звучит тривиально, но когда дело доходит до проблем с набором символов, это всегда работает для меня;)

2 голосов
/ 25 января 2009

Локализация довольно сложная.

Я думаю, вы действительно задаете два вопроса. Один из них, как заставить всех правильно работать с приложением i8n, на мой взгляд, не технический, а вопрос управления проектами. Если вы хотите, чтобы люди использовали общий стандарт, такой как UTF-8, то вам просто нужно будет применить его. Инструменты помогут, но сначала нужно будет попросить людей сделать это.

Помимо того, что, по моему мнению, UTF-8 - это путь, трудно дать ответ на вопросы об инструментах. Это действительно зависит от того, какой проект вы делаете. Если, например, речь идет о проекте Java, о котором вы говорите, то это просто вопрос правильной настройки среды IDE для кодирования файлов в UTF-8. И чтобы убедиться, что ваши локализации UTF-8 находятся во внешних файлах ресурсов.

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

1 голос
/ 30 января 2009

В PHP мы используем функции mb_, такие как mb_detect_encoding () и mb_convert_encoding (). Они не идеальны, но они дают нам 99,9% пути. Чем у нас есть несколько регулярных выражений, чтобы убрать забавные символы, которые каким-то образом оказываются там время от времени.

Если вы выходите на международный уровень, вы определенно хотите использовать UTF-8. Нам еще предстоит найти идеальное решение для передачи всех наших данных в UTF-8, и я не уверен, что оно существует. Надо просто возиться с этим.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...