Однажды у Колина появился клиент с вопросом о неожиданном поведении функции
TranslateCharsetInfo
:
У моего клиента есть проблемы с APIРезультаты двух значений LCID на самом деле вызваны двумя совершенно различными причинами.TranslateCharsetInfo
. Они указывают флагTCI_SRCLOCALE
для использования LCID как источника:fResult := TranslateCharsetInfo(langid, csi, TCI_SRCLOCALE);Они обнаружили, что результаты этого вызова не всегда соответствуют значениям, указанным в http://www.microsoft.com/globaldev/nlsweb/default.mspx
В частности:
LCID$0C04
– Chinese (Hong Kong S.A.R.) - возвращает кодовую страницу 936 вместо ожидаемой 950
LCID$0004
- Chinese (Simplified) – возвращает кодовую страницу 950 вместо ожидаемой 936
То, что я вижу - это ожидаемое поведение или нет? Если нет, то какой есть другой способ?
Мы также попробовали:GetLocaleInfo(langid, LOCALE_IDEFAULTANSICODEPAGE, szLocaleData, SizeOf(szLocaleData)/SizeOf(Char));Хотя этот способ возвращает 950 для LCID$0C04
(уже лучше), но LCID$0004
всё ещё возвращает 950 вместо 936.
Или я что-то упускаю?
Many thanks,
Colin
В обоих случаях GDI зависит от информации, возвращаемой
GetLocaleInfo
с значением LOCALE_FONTSIGNATURE
для LCTYPE
. Другими словами, GDI зависит от NLS.В одном случае тот факт, что .NET Framework рассматривает
$0004
как "Simplfied Chinese", даже хотя вот уже несколько версий Windows обрабатывают нейтральный LCID как имеющий неявный SUBLANG_DEFAULT
, делая его $0404
(Chinese - Taiwan, традиционная китайская локаль), может быть рассмотрен как недостаток дизайна NLS, который был исправлен только в Vista (через функцию ConvertDefaultLocale
, которая управляет логикой всех NLS API функций, пропускающих через себя LCID.Другими словами, это был баг, который больше не воспроизводится в Vista :-)
Теперь насчёт второй половины вопроса. Давайте используем секретный парсинг
LOCALESIGNATURE
функции CultureAndRegionInfoBuilder
с простым кодом вроде такого:using System; using System.Globalization; namespace LDML { class LDML { [STAThread] static void Main(string[] args) { CultureAndRegionInfoBuilder carib = new CultureAndRegionInfoBuilder(args[0], CultureAndRegionModifiers.Replacement); carib.LoadDataFromCultureInfo(new CultureInfo(args[0], false)); carib.LoadDataFromRegionInfo(new RegionInfo(args[0])); carib.Save(args[0] + ".ldml"); } } }Тогда, если вы сохраните этот код в файл ldml.cs и скомпилируете его:
csc ldml.cs /r:sysglobl.dllто вы можете сохранить LDML, который использует zh-HK (
$0C04
), и посмотреть на разметку:
<msLocale:fontSignature> <msLocale:unicodeRanges> <mslocale:range type="0"> <mslocale:range type="1"> <mslocale:range type="2"> <mslocale:range type="3"> <mslocale:range type="5"> <mslocale:range type="7"> <mslocale:range type="9"> <mslocale:range type="31"> <mslocale:range type="35"> <mslocale:range type="36"> <mslocale:range type="37"> <mslocale:range type="38"> <mslocale:range type="39"> <mslocale:range type="42"> <mslocale:range type="43"> <mslocale:range type="45"> <mslocale:range type="46"> <mslocale:range type="48"> <mslocale:range type="49"> <mslocale:range type="50"> <mslocale:range type="51"> <mslocale:range type="54"> <mslocale:range type="59"> <mslocale:range type="60"> <mslocale:range type="68"> </msLocale:unicodeRanges> <msLocale:defaultCodePages> <msLocale:ansiCodePage /> <msLocale:ansiOemCodePage> <msLocale:codePage type="936" /> </msLocale:ansiOemCodePage> <msLocale:oemCodePage /> </msLocale:defaultCodePages> <msLocale:codePages> <msLocale:ansiCodePage /> <msLocale:ansiOemCodePage> <msLocale:codePage type="936" /> </msLocale:ansiOemCodePage> <msLocale:oemCodePage /> </msLocale:codePages> </msLocale:fontSignature>Обратите особое внимание на кодовую страницу, которую имеет
LOCALESIGNATURE
(отмечено КРАСНЫМ). Так что, технически, это не вина GDI (возвращение неверной информации), потому что GDI просто использовал данные NLS.Хотя, снова технически, вы не можете винить и NLS, потому что все данные
LOCALESIGNATURE
предоставляются нам командой типографии. Когда-нибудь мы можем захотеть от них обновление, такое чтобы GetLocaleInfo
смогла возвращать согласованные результаты от LOCALE_IDEFAULTANSICODEPAGE
, LOCALE_IDEFAULTCODEPAGE
и LOCALE_FONTSIGNATURE
...Хотя, как это исправить - это интересный вопрос.
В теории, учитывая увеличивающееся в последние годы использование упрощённого китайского в Гонконге, было бы интересным изменение кодовой страницы по-умолчанию
LOCALESIGNATURE
на 950, но указание обеих страниц 936 и 950 в секции кодовых страниц. С описательной точи зрения в этом есть смысл.Однако на практике raison d'être
LOCALESIGNATURE
- предоставлять информацию для создания имеющего смысл шрифта по-умолчанию для локали. И, вообще говоря, у кого-нибудь может не быть шрифтов, поддерживающих обе кодовые страницы. Так что лучшее исправление, вероятно, просто сделать так, чтобы LOCALESIGNATURE
совпадала бы с локалью, в которой она сидит...This post brought to you by ញ (U+1789, KHMER LETTER NYO)
*шёпотом, забившись в угол*
ОтветитьУдалить- Я вижу русские буквы в url!.. :)
P.S. Из rss в конец url опять кракозябры дописываются...
Да, я вот тоже заметил :D
ОтветитьУдалитьP.S. А что там с RSS?
> А что там с RSS?
ОтветитьУдалитьСсылка, открытая из читалки Feedreader 3.14 на эту статью выглядит так. Раньше тоже был мусор, потом пропал, теперь опять вернулся.
А, это нормально. Так должно быть. Это отслеживаются заходы по RSS в FeedBurner.
ОтветитьУдалитьЕсли я ничего не путаю, конечно.