- PVSM.RU - https://www.pvsm.ru -

Локализация и глобализация

В статье автор пытается очертить некоторые необходимые для понимания аспекты интернационализации в .NET, особенности китайской и не только локализаций, и несколько забавных моментов.

Терминология

Приведу несколько вольно переведенных и отредактированных определений из MSDN:

Локализация (Localization) — это процесс перевода ресурсов приложения в локализованные версии для каждого языка и региональных параметров, которую поддерживает приложение. Переход локализации должен происходить только после того, как выполнена условие Локализуемости (Localizability), т.е. исполняемый код отделен от любых элементов пользовательского интерфейса.

Глобализация (Globalization) — это процесс проектирования и разработки приложения, которое поддерживает локализованный пользовательский интерфейс и региональные данные для пользователей из разных культур. Cведения о конкретных языковых и региональных параметрах могут включать в себя: систему письма, используемые календари, соглашения о формате даты и времени, чисел, денежных и физических величин, правила сортировки и даже форматы адреса, телефона, размера бумаги по умолчанию.

Так что то, чем занимаются команды, приводящие к потребному виду изначально нелокализуемые продукты, называется громким словом — глобализацией, но никак не локализацией.

Локализация и глобализация [1]

Язык и региональные стандарты

Итак, в .NET есть главный класс, представляющий информацию о языковых и региональных стандартах (для неуправляемого кода по-английски называемых ''locale'') — System.Globalization.CultureInfo [2]. Рядом с ним есть еще Calendar, RegionInfo, NumberFormatInfo, DateTimeFormatInfo и мн. др.

У культуры есть имя (по сути — код), в этих терминах удобно общаться. У инвариантной культуры имя пустое, поэтому мы будем обозначать её как ivl.

Две культуры потока

У любого потока — экземпляра Thread есть два свойства: public CultureInfo CurrentCulture {get; set;} и public CultureInfo CurrentUICulture {get; set;}
Первая культура используется для форматирования чисел, дат и пр. региональных настроек, а вторая используется в алгоритме [3] поиска подходящих локализованных ресурсов.

Так зачем же нужно две культуры? В этом есть резон: для потомка англосаксов, родившегося и живущего в Индии, родной язык — английский. На нем он и хочет видеть интерфейсы программ на своем ноутбуке. Однако, при работе в Excel'е он скорее всего будет оперировать рупиями (буква रु на хинди), и при этом знает, что площадь родной страны составляет 32,87,590.01 км2.

Локализация и глобализация

Структура дерева культур

Культуры образуют дерево. Т.е. у каждой культуры есть родительская.

В корне дерева расположена «никакая» культура — инвариантная. Она не содержит в себе информацию о регионе, представляет несуществующий инвариантный язык, правила форматирования в котором странным образом похожи на американские. Родителем инвариантной культуры является другая инвариантная культура, и так до stack overflow.

Противоположностью являются определенные (специфичные, specific) культуры. Они содержат в себе информацию и о языке/письме, и о регионе, и о форматировании чисел и дат. Примеры: ru-RU, en-US, en-IN.

Родителями специфичных культур культур являются нейтральные культуры. Назначение таких культур — нести информацию о языке и письме. До .NET 4.0 нейтральные культуры и не могли содержать информацию о форматировании и регионе, теперь эта информация берется из доминирующей специфичной культуры. Примеры: ru, en, mn-Cyrl (монгольский, кириллица), mn-Mong (старомонгольское письмо).

Вопрос на засыпку внимательному читателю: кто может быть родителем нейтральной культуры?

Распространенные заблуждения

Итак, мы с легкостью представляем веточку дерева культур на примере ivl <— ru <— ru-RU. Но неверно утверждать, что иерархия всегда состоит из трех культур. Так, например, думали авторы книги Язык программирования C# 2005 для профессионалов [4] в примере к 17-й главе, и тогда это было почти верно [5].

Но языки с несколькими видами письма ломают стереотип.

Локализация и глобализация

До .NET 4.0 все было совсем запутанно: существовали специфичные культуры, родителем которых была инвариантная. См. тулу [6].

Китайский куст

Локализация и глобализация

На китайском [7] говорят свыше 1,3 млрд человек, официальным является в Китайской Народной Республике, Китайской Республике (aka Тайвань) и Сингапуре. И не забудьте о специальных административных районах — Гонконге и Макао.

Существует два вида китайского письма: упрощенное (с 1956 г.) и традиционное. Традиционно китайцы писали сверху вниз, а столбцы шли справа налево. Совсем недавно, с 2004 г., на Тайване перестали официально использовать вертикальное письмо. Сейчас используется «европейский» способ письма [8] — горизонтально слева направо.

Вернемся к .NET'у. Культуры zh-CHS и zh-CHT в .NET 2.0 были объявлены устаревшими и заменены на zh-Hans и zh-Hant. В дереве культур zh-Hans является родителем zh-CHS для корректной работы fallback process [3]. В дальнейшем с любым патчем устаревшие культуры могут пропасть.

Отдельно подчеркну, что на территории КНР используются оба вида письма: в Гонконге и Макао — традиционное, на остальной бoльшей территории — упрощенное.

Fallback process

Для поиска подходящих ресурсов (текста, координат и размеров контролов, иконок и мн. др.) экземпляр ResourceManager смотрит на Thread.Current.CurrentUICulture. UI-культура может быть как специфичной, так и нейтральной. А вот Thread.Current.CurrentCulture м.б. только специфичной культурой.

Сначала менеджер ресурсов пытается найти ресурсы, чья культура совпадает с UI-культурой. Если не находит, то берет родительскую культуру и повторяет поиск. Если таким образом мы дойдем до инвариантной культуры, то придется использовать ресурсы по умолчанию (нейтральные) (часто они расположены в основной сборке, но не обязательно).

Правда, ресурсы по умолчанию тоже могут быть помечены культурой. См. подробности в MSDN [9].

Косяки от MS

№1

Вашему вниманию представлен еще один кустик культур — узбекский:

Локализация и глобализация

Понятно, что произошло: после 1991 г. когда-то переведенные на кириллицу языки стали усиленно от кириллицы избавлять.

У класса CultureInfo есть свойство string NativeName, т.е. название культуры на описываемом языке. Для культуры uz-Latn-UZ значение NativeName равно U'zbek (U'zbekiston Respublikasi), хотя на самом деле должно быть O'zbek (O'zbekiston Respublikasi).

Багу уже много версий .NET.

№2

Поговорим про бывшую союзную республику Молдавию [10], самоназвание ''Молдова''. Говорят молдаване на молдавском языке. Хотя ученые-филологи спорят, что это не самостоятельный язык, а диалект румынского.

По факту, существует три румынских языка:

  • румынский в Румынии (латиница);
  • румынский в Приднестровье (кириллица), оставшийся в том виде, в каком был на момент распада Союза;
  • румынский в Молдавии (латиница), со своим вариантом латинизации, не совпадающем с принятым в Румынии.

Казалось бы, в .NET мы можем ожидать увидеть три специфичные румынские культуры, ну, или две — по политическим причинам (Приднестровье). Но нет, Молдавии в Windows NLS API [11] нет. Есть только культура ro-RO, Румынский (Румыния). Именно такой локалью молдавские пользователи и пользуются. Зато Microsoft в Молдавии есть [12].

Ну и конечно же, .NET позволяет создавать собственные культуры.

Интересно, что когда-то давно, в первых .NET'ах и старых операционках были замечены культуры ru-MO и ro-MO. Да, код региона был MO, а не MD как сейчас. Стандарт ISO поменялся?

Табу для локализуемых приложений

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

№1

Очевидно, что никогда нельзя зашиваться на имена системных папок. Хотя, казалось бы, куда могут подеваться Program Files? По какой-то нелепости в локализованной на русский Windows эту папку не стали переименовывать. Но так не во всех локализациях!

В испанской локализации папка гордо именуется Archivos de programa. Рекомендую: перевод Гугла [13] с испанского на русский.

№2

Настоящим бичом глобализуемого-локализуемого приложения являются строки. Конкатенирующиеся. Но даже если строки с подстановками, то переводчикам содержимое подстановок без комментариев неочевидно: "{0}" вызвало ошибку "{1}".{2}Обратитесь к {3}. А под {2} имеется в виду банальный Environment.NewLine.

Ссылки

MSDN

Статьи

Инструменты

Автор: vlio

Источник [21]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/razrabotka/25095

Ссылки в тексте:

[1] Image: http://msdn.microsoft.com/en-us/goglobal/bb688112

[2] System.Globalization.CultureInfo: http://msdn.microsoft.com/en-us/library/system.globalization.cultureinfo.aspx

[3] алгоритме: #Fallback_process

[4] Язык программирования C# 2005 для профессионалов: http://www.ozon.ru/context/detail/id/2764114/

[5] почти верно: http://msdn.microsoft.com/en-us/library/system.globalization.cultureinfo(v=vs.85).aspx

[6] тулу: https://www.dropbox.com/s/1ngl71jej6km32v/CultureDemoHabrahabr.zip?dl=1

[7] китайском: http://ru.wikipedia.org/wiki/%D0%9A%D0%B8%D1%82%D0%B0%D0%B9%D1%81%D0%BA%D0%B8%D0%B9_%D1%8F%D0%B7%D1%8B%D0%BA

[8] способ письма: http://ru.wikipedia.org/wiki/%D0%9A%D0%B8%D1%82%D0%B0%D0%B9%D1%81%D0%BA%D0%BE%D0%B5_%D0%BF%D0%B8%D1%81%D1%8C%D0%BC%D0%BE#.D0.9D.D0.B0.D0.BF.D1.80.D0.B0.D0.B2.D0.BB.D0.B5.D0.BD.D0.B8.D0.B5_.D0.BF.D0.B8.D1.81.D1.8C.D0.BC.D0.B0

[9] MSDN: http://msdn.microsoft.com/en-us/library/sb6a8618.aspx

[10] Молдавию: http://ru.wikipedia.org/wiki/%D0%9C%D0%BE%D0%BB%D0%B4%D0%B0%D0%B2%D0%B8%D1%8F

[11] Windows NLS API: http://msdn.microsoft.com/en-us/goglobal/bb896001

[12] есть: http://www.microsoft.com/ro-md/default.aspx

[13] перевод Гугла: http://translate.google.com/#es/ru/Archivos%20de%20programa

[14] .NET Framework 4: What's New in Globalization and Localization: http://msdn.microsoft.com/en-us/library/vstudio/dd997383(v=vs.100).aspx

[15] Globalizing and Localizing .NET Framework Applications (.NET Framework 4.5): http://msdn.microsoft.com/en-us/library/h6270d0z.aspx

[16] WPF: Globalization and Localization: http://msdn.microsoft.com/en-us/library/ms753931(v=vs.100).aspx

[17] Глава из книги “ Язык программирования C# 2005 для профессионалов”: http://www.rsdn.ru/article/dotnet/csprof2005_localization.xml

[18] примерами: http://www.rsdn.ru/article/dotnet/csprof2005_localization/Chapter17.rar

[19] zh-Hans, zh-Hant and the «old» zh-CHS, zh-CHT: http://blogs.msdn.com/b/shawnste/archive/2007/12/13/zh-hans-zh-hant-and-the-old-zh-chs-zh-cht.aspx

[20] The 'Program Files' folder in different languages: http://www.samlogic.net/articles/program-files-folder-different-languages.htm

[21] Источник: http://habrahabr.ru/post/166053/