Как сделать локализацию в c

Обновлено: 01.07.2024

Мне интересно, могу ли я получить несколько примеров самых простых / лучших способов сделать это.

Я лично хотел бы что-то вроде настроек приложения

Там, где я обычно делал MyApplication.Properties.Settings.Default.SomeKey , я надеялся, например, на MyApplication.Languages.Current.ApplicationTitle и MyApplication.Languages.en.ApplicationTitle .

Также было бы полезно загружать только один ресурс для каждого языкового файла для повышения скорости.

Что вы думаете об этом?

Класс MenuLocaleInfo

Класс MenuLocaleInfo представляет собой объект, с помощью которого мы свяжем элемент любого нашего "языкового" меню и соответствующую ему локаль. Например, для меню mnuLangRus ("Русский") соответствующая локаль будет "ru-RU", для меню mnuLangEng ("English") - "en-GB" и т. д. Итак, класс содержит поле m_menuItems - указатель на пункт меню и строку m_sLocale, содержащую локаль. Создадим конструктор таким образом, чтобы он принимал два параметра, сразу инициализирующий оба поля класса:

Класс AppLangChangedArgs

Класс AppLangChangedArgs будет содержать единственное поле - ссылку на объект класса CultureInfo. Примечательной особенностью класса является то, что мы наследуем его от стандартного класса System.EventArgs. Это делается для того, чтобы использовать объект класса AppLangChangedArgs в качестве параметра в любых методах форм, которые будут реагировать на событие "смена языка приложения". Такое событие нужно для того, чтобы вызвать смену языка во всех частях нашего приложения и динамически сменить язык везде. Если бы у нас в программе было не две, а 20 форм, то в каждой из них мы могли бы создать метод, реагирующий на событие смены языка. Чуть дальше, когда мы определим делегат и событие это станет более понятно. А пока код класса:

5. Добавляем код к основной форме

Код главной формы я буду рассматривать по частям. Полный архив с исходниками приложения есть в конце статьи. Итак, в классе главной формы определяем массив элементов типа MenuLocaleInfo, а также создаем делегат AppLanguageChangedHandler, описывающий метод для смены языка и соответствующее ему событие - AppLanguageChanged. Событие AppLanguageChanged делаем публичным и статическим, что позволит нам "отлавливать" его в любом месте приложения. (Для примера, мы сделаем это как раз во всплывающей форме frmPopupForm). В конструкторе главной формы привязываем событие к методу frmSimpleLocalization_AppLanguageChanged (создаем его сами), который, по сути, и будет выполнять всю работу по переводу интерфейса на разные языки:

Создаем метод InitLocaleInfo(). Его мы вызовем сразу после загрузки главной формы. Суть метода в следующем: мы инициализируем наш массив элементов типа MenuLocaleInfo. Легко видеть, что в качестве конструктора мы передаем пункт определенного меню и соответствующую ему локаль:

В дальнейшем, если будет необходимо добавить новые языки, просто добавим их в массив. Теперь рассмотрим событие загрузки формы. В нем как раз вызывается описанный только что метод InitLocaleInfo(), после чего мы обращаемся через Properties.Settings.Default.Locale к нашей настройке, которая хранит текущий язык. Т.е. при загрузке формы получаем текущий язык, тут всё понятно. Следующий шаг - пробегаем по массиву элементов MenuLocaleInfo и для каждого из них сверяем текущий язык приложения и локаль, привязанную к пункту меню. Если обнаруживается, что они совпадают, вызываем метод PerformTranslation (его рассмотрим далее), передавая в качестве ссылки пункт меню:

Далее рассмотрим метод PerformTranslation. Он принимает параметр типа object, в который на самом деле мы будем передавать ссылку на пункт меню. Цель метода - пробежать по всем пунктам меню, сбросить для них флажок, если они не являются текущим языком приложения и установить флажок для того пункта меню, который соответствующего текущему языку. Также метод производит перевод приложения на выбранный язык следующим образом: мы меняем локаль приложения, возбуждаем событие смены языка (глобально, его получат все подписчики, т.е. другие формы приложения) и, наконец, если локаль была сменена, сохраняем её в настройках:

Последнее, что осталось добавить в код главной формы - обработчики для пунктов меню и кнопок. Тут всё просто - в обработчиках меню вызываем PerformTranslation()

6. Добавляем код к всплывающей форме

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

Подавляющее число примеров кодов со строками C/C++ (в любых публикуемых источниках) оперирует с нуль-терминальными массивами (ASCIZ) элементов char (в стиле C), или с контейнерным типом string (в стиле C++), построенным как надстройка над такими массивами.

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

Язык C — весьма старый язык программирования, а C++ наследует из него форматы и сдерживается требованиями синтаксической совместимости с C. Для того, чтобы не иметь в C/C++ проблем с такими строками (называемыми локализованными) нужно понимать что там с этими локализациями происходит…

Такая кодировка позволяет кодировать максимально всего 128 различных символов, и этого числа с трудом хватает на символы английского алфавита (большие и малые), цифровые (коды 0x30-0x39), управляющие (код меньше 0x20) и специальные символы. Когда возникала необходимость представления национальных алфавитов, вводилась альтернативная таблица символов, например KOI-7 для русского языка.

Переключение в потоке ввода-вывода на альтернативную таблицу символов производилось символом с кодом 0x18 (код называется: Device Control 2) в потоке, а возврат к основную таблицу ASCII — символом с кодом 0x17 (Device Control 1).

Но, поскольку национальные алфавиты могут быть самыми разнообразными, то для поддержки каждого из них потребовалось ввести свою кодовую страницу, например, для русского языка это могут быть страницы CP-866 (в MS-DOS), CP-1251 (в Windows), KOI-8r (в UNIX, Linux) — и каждая из этих страниц предлагает свой, отличающийся от других, порядок символов русского языка. При этом, для корректного отображения (или декодирования) любой локализованной символьной строки нужно обязательно знать кодовую страницу в которой она представлена.

Для того, чтобы положить конец этому вавилонскому столпотворению языковых кодовых страниц, был предложен (1991г.) стандарт представления UNICODE, в системе кодирования которого каждый символ кодируется 32-бит значением (4 байта, но не все 32-бит значения допустимы). Применение данного стандарта позволяет закодировать огромное количество символов разных систем письменности.

Документы, закодированные по стандарту UNICODE, могут содержать в едином тексте японские и китайские иероглифы, буквы латиницы, кириллицы, греческого алфавита (α, ε, θ, π, σ, λ, φ, Ω…), математические символы, символы музыкальной нотной нотации, символы вымерших, редких, экзотических народностей. При этом нет необходимости в переключении кодовых страниц. Например, вот как выглядят некоторые символы языка, обозначенного как “сингальский”:

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

Возникла проблема с отображением русских букв

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

После написания, компиляции и запуска такой программы:

Можно получить примерно такой результат

Вывод кракозябр в консоль

Вывод кракозябр в консоль

Сразу понятно, что на приветствие это совсем не похоже.

После прочтения кучи советов стало понятно, что большая часть советов предлагала решить проблему функцией setlocale(), которая находится в заголовочном файле .

Последовав совету и усовершенствовав программу таким образом:

На вывод я получил следующий результат

Привет, Мир!

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

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

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

Но в результате я получил не приветствие

Оскорбление на древнеегипетском?

Оскорбление на древнеегипетском?

Как видно, она не смогла назвать моего имени.

Поискав информацию в сети, я узнал о том, что setlocale() не работает с потокоми ввода/вывода, а то есть с cin,cout,etc. Выходит, что нужно искать альтернативные способы решения данной проблемы, которые предлагались на других сайтах.

Решение проблемы с отображением русских букв в консоли

По-другому решить проблему можно было воспользовавшись функциями SetConsoleCP() и SetConsoleOutputCP() с аргуменом 1251 в обеих. Эти функции требуют подключения заголовка , практически в каждом компиляторе под Windows он имеется, проблем не будет.

Усовершенствовал программу таким образом

На вывод получил

Вновь кракозябры в консоли

Вновь кракозябры в консоли

Контекстное меню консоли

Контекстное меню консоли

Далее появится окно с настройками, там необходимо выбрать шрифт Lucida Console.

Свойства консоли Windows

Свойства консоли Windows

И нажать на кнопку ОК.

После такой процедуры я вновь запустил программу и…

Работа программы

Да! Она поздоровалась со мной по имени на русском языке.

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

Для вас это может быть интересно:

Русские символы(буквы) при вводе/выводе в консоль на C++ : 28 комментариев

using namespace std;

В консоли 866 кодовая страница. Можно проще — Creator — Настройки — редактор — кодовая страница 866. Заработает самая первая программа.

Спасибо за 866 кодовую таблицу, все заработало.

Мучался 2 часа с выводом русских букв!
Перечитал кучу пустых советов.
Наконец-то.
Этот— самый толковый способ сделать так, чтобы все работало, и писало по русски!!
Благодарю Вас.

Я рад тому, что это помогло мне, Вам и другим людям.

Вижу, что не только в вебе проблема с отображением русских букв. PHP- программисты с вами!

Большое человеческое спасибо!
Очень помогли дельным советом. Всё работает как надо!

Спасибо!по полочкам и правильно всё разложено)

На мой взгляд, самый простой и действенный способ вывода русских букв в консоли Windows: писать исходники в ее родной кодировке, т. е. в OEM866 и проблем никаких не возникнет. Тем более, что почти все текстовые редакторы ее поддерживают. Для удобства можно установить эту кодировку по умолчанию в тот же Notepad++.
И не надо танцевать с бубном, подключать заголовки, использовать дополнительные функции, менять шрифты и т.д.

Спасибо, дай те бог здоровья!!

Благодарю за эти советы, они действующие, доходчивые. Ушла минута на то, что долго не мог сделать

6 часов искал ответ!Спасибо !

Имеется ввиду после фигурных скобок, т.е. в тело программы

Спасибо большое!Очень помогло.С начала про поток вывода узнал где то недели 2 назад, вчера заинтересовало почему поток ввода не работает. Менее минуты и вуаля. Надеюсь ругаться там не будет никто на счёт заголовочных файлов, но…ОС у всех разные, преобразователи (компиляторы) разные. Вот поэтому и советы для всех разные. Кому то кодировку сменить, а многим многим остальным дополнительные код надо писать. Может когда напишем собственную ОС(хотя кое что такое у нас было когда то давно) тогда ничего этого не надо будет. Автору статьи большое спасибо ещё раз. Русский язык стараюсь вписать куда угодно лишь бы было по русски. Надеюсь, это никого не задевает

Читайте также: