Решено: C/C++ wide-литералы и wstrings: как с этим работать УДОБНО? как подружить с gettext?

Модератор: Модераторы разделов

sergio
Сообщения: 436
Статус: Интересующийся новичок
ОС: Debian GNU/Linux 4 & 5

Решено: C/C++ wide-литералы и wstrings: как с этим работать УДОБНО? как подружить с gettext?

Сообщение sergio »

Вопрос такой:
программа работает с wstring-ами; помимо того в ней пользуются и литералы. Конвертировать все строки ручками при выводе мне как-то не улыбается, я бы их лучше через wcout выпустил. Пользовать потоки двух сортов вперемешку мне тоже не улыбается. Значит надо L'литералы применять. Отсюда вопрос:
Есть способ заставить препроцессор считывать содержимое

Код: Выделить всё

const wchar_t* = L"Всем привет!"

в штатной кодировке то бишь UTF-8 и подставлять туда юникод-ескейпы перед отдачей компилятору?

Что делает -fwide-exec-charset=UTF8 из документации не понял, но то что хочецо он не делает.

Плюс вопрос, как можно загружать эти широкие строки из месидж каталогов. Дока к gettext об этом не заикается, в списке поддерживаемых в PO файлах кодировок только UTF8.
Debian GNU/Linux 4 -- AMD Athlon64 3000+ / Asus 7600GS -- Gnome
Debian GNU/Linux 5 -- Dell (Vostro) 500 (Celeron M560 / iGM965) -- Gnome
Спасибо сказали:
d_n_k
Сообщения: 636
ОС: Gentoo GNU/Linux

Re: Решено: C/C++ wide-литералы и wstrings: как с этим работать УДОБНО? как подружить с gettext?

Сообщение d_n_k »

Плюс вопрос, как можно загружать эти широкие строки из месидж каталогов. Дока к gettext об этом не заикается, в списке поддерживаемых в PO файлах кодировок только UTF8.

info gettext
все сказанное есть имхо...
Спасибо сказали:
sergio
Сообщения: 436
Статус: Интересующийся новичок
ОС: Debian GNU/Linux 4 & 5

Re: Решено: C/C++ wide-литералы и wstrings: как с этим работать УДОБНО? как подружить с gettext?

Сообщение sergio »

d_n_k писал(а):
11.09.2007 00:16
Плюс вопрос, как можно загружать эти широкие строки из месидж каталогов. Дока к gettext об этом не заикается, в списке поддерживаемых в PO файлах кодировок только UTF8.

info gettext

Ну спасибо, что не
man linux
ответили. :D
Конкретнее можно? Где написано про загрузку широких строк?
Судя по оглавлению в info gettext он идентичен http://www.gnu.org/software/gettext/manual...node/index.html
В таком случае я это все смотрел. Ни одного примера с wчто-нибудь в си я там не заметил. Что я делаю не так?


2All:
Кстати, там давно обруганная поддержка месиджей в стандартной библиотеке Си++ была... А она вообще как-нибудь работает? или так и осталась комитетным проектом? где бы на эту тему пошукать?..
Debian GNU/Linux 4 -- AMD Athlon64 3000+ / Asus 7600GS -- Gnome
Debian GNU/Linux 5 -- Dell (Vostro) 500 (Celeron M560 / iGM965) -- Gnome
Спасибо сказали:
v04bvs
Сообщения: 636
ОС: Debian GNU/Linux

Re: Решено: C/C++ wide-литералы и wstrings: как с этим работать УДОБНО? как подружить с gettext?

Сообщение v04bvs »

Стандартными средствами С++ с юникодом работать неудобно, это факт. Советую взять Qt, там всё попроще будет.

А так - обычно компилятор трактует исходный текст в кодировке локали. Хотя я лично считаю, что любой программный текст ОБЯЗАН быть в 7-битной кодировке ASCII, а все национальные строки должны подгружаться из внешних ресурсов.
Спасибо сказали:
Аватара пользователя
nonstop
Сообщения: 132
ОС: Slackware

Re: Решено: C/C++ wide-литералы и wstrings: как с этим работать УДОБНО? как подружить с gettext?

Сообщение nonstop »

1. Стандартный C++ не умеет работать с UTF-8
2. Есть специальные библиотеки для этой цели (glibmm, ICU)
3. manual к gettext очень подробный, так все описано как делать
4. если использовать gettext, следует придерживаться установленных правил оформления переводимых строк.
Судя по записи L"msg", это пришло из-под Visual Studio, так вот следует писать

Код: Выделить всё

#define _(String) gettext(String)

5. po-файлы поддерживают массу кодировок, просто ее нужно указать в заголовке po-файла

Код: Выделить всё

"Content-Type: text/plain; charset=UTF-8\n"
slackware - linux for human brains
Спасибо сказали:
sergio
Сообщения: 436
Статус: Интересующийся новичок
ОС: Debian GNU/Linux 4 & 5

Re: Решено: C/C++ wide-литералы и wstrings: как с этим работать УДОБНО? как подружить с gettext?

Сообщение sergio »

Так, с одной половиной вопроса я разобрался...
nonstop писал(а):
11.09.2007 09:20
1. Стандартный C++ не умеет работать с UTF-8

Смотря что понимается под "работой". Если хранение литералов ютф-8, их ввод-вывод, и работа со строками string в ютф8 - то умеет замечательно, но с оговорками, которые надо знать (все те фу-и которые работают собственно с текстом и буквами есессно не работают, итераторы по строкам тоже).
2. Есть специальные библиотеки для этой цели (glibmm, ICU)

Да, IBM ICU. На неск десятков мегабайт весом. Но для чтения-вывода строк и набора литералов в программе они не нужны.
3. manual к gettext очень подробный, так все описано как делать

Да, и с ютф-8 оно прекрасно-не прекрасно, то по крайней мере как-то - работает. Уже проверял.
4. если использовать gettext, следует придерживаться установленных правил оформления переводимых строк.
Судя по записи L"msg", это пришло из-под Visual Studio, так вот следует писать

Код: Выделить всё

#define _(String) gettext(String)

Нет. L"abcdef\u1234\U00001234fghty" пришло из стандарта языка, как и L'a', а никак не из МСВС. Это широкие символьные и строковые литералы, а фунции gettext служат для загрузки обычных.
5. po-файлы поддерживают массу кодировок, просто ее нужно указать в заголовке po-файла

Код: Выделить всё

"Content-Type: text/plain; charset=UTF-8\n"

PO-файлы - да, и ладно. Меня интересует загрузка L-литералов. Они загружаются не в UTF-8, а (для i386/amd64 GNU/Linux) в UTF-32LE. Значит или MO файл должен создаваться для такого, или, скорее, в PO файле часть строк должны помечаться как широкие. И должны быть функции для работы с ними.

v04bvs
Стандартными средствами С++ с юникодом работать неудобно, это факт. Советую взять Qt, там всё попроще будет.

Только что ковырялся в TagLib, которая-де косит под куте-стиль, и даже живет в сети где-то на кутешных сайтах, - там доморощенный класс String реализован как обертка вокруг std::wstring.
Qt ладно, мне пока охота разобраться с этим как-нибудь, без лишних мегатонн библиотек.

А так - обычно компилятор трактует исходный текст в кодировке локали. Хотя я лично считаю, что любой программный текст ОБЯЗАН быть в 7-битной кодировке ASCII, а все национальные строки должны подгружаться из внешних ресурсов.

Трактует, так и есть. Все оказалось смешнее, щас расскажу.

Короче, вот это

Код: Выделить всё

  #include <iostream>
  int main()  {
    setlocale(LC_ALL, "");

    std::wcout << L"Всем привет!" << std::endl;

    std::wstring wstr;
    std::wcin >> wstr;
    std::wcout << L'[' << wstr << L']' << std::endl;

    return  0;
  }


работает как предполагается. Локаль надо включать, иначе конвертор в wstream-ах работает в "C", все ломая. Это я так догадываюсь.

Остается вопрос с каталогами-месиджами и чем-нибудь gettext-подобным...


UPD
(задумчиво) В принципе, я конечно могу забить строки в каталог UTF-8, и для gettext попробовать сочинить обертку, чтоб конвертила их в UTF32 при загрузке... Как-то это все немного извратно. ;-/
Debian GNU/Linux 4 -- AMD Athlon64 3000+ / Asus 7600GS -- Gnome
Debian GNU/Linux 5 -- Dell (Vostro) 500 (Celeron M560 / iGM965) -- Gnome
Спасибо сказали:
d_n_k
Сообщения: 636
ОС: Gentoo GNU/Linux

Re: Решено: C/C++ wide-литералы и wstrings: как с этим работать УДОБНО? как подружить с gettext?

Сообщение d_n_k »

В таком случае я это все смотрел. Ни одного примера с wчто-нибудь в си я там не заметил. Что я делаю не так?

а кто сказал что gettext знает про w<бла-бла-бла>?
w<бла-бла-бла> - это stl'ная байда

думаю вам также надо почитать info info

а чтоб вы дальше не тупили вот вам ссылочка на индекс http://www.gnu.org/software/gettext/manual...ndex.html#Index // регистр имеет значение ибо это вам не винда

а вот сюда приводит первое совпадение если искать по строке "charset" http://www.gnu.org/software/gettext/manual...rset-conversion
все сказанное есть имхо...
Спасибо сказали:
sergio
Сообщения: 436
Статус: Интересующийся новичок
ОС: Debian GNU/Linux 4 & 5

Re: Решено: C/C++ wide-литералы и wstrings: как с этим работать УДОБНО? как подружить с gettext?

Сообщение sergio »

Многоуважаемый господин d_n_K! Большое спасибо, что вы поучили меня пользоваться info, что вы поучили меня пользоваться индексом (в котором регистр имеет значение, ибо это нам не винда), что вы поучили меня жизни и ваще поучили не тупить.
Но если вы не догадываетесь, что функция

Код: Выделить всё

char *gettext (const char *msgid);

плохо приспособлена для загрузки широких строк, и если библиотека непосредственно поддерживает эту загрузку, то в ней должна быть для этого более подходящая функция, например

Код: Выделить всё

wchar_t *gettext (const wchar_t *msgid);

то вы б хотя бы прочитали то, что написано на той странице, на которую вы так щедро кинули нам, убогим, ссылку:
d_n_k писал(а):
12.09.2007 15:46
а вот сюда приводит первое совпадение если искать по строке "charset" http://www.gnu.org/software/gettext/manual...rset-conversion

ведь там всего три абзаца, и достаточно их прочесть, чтобы понять, что нормально загружать wide-строки эта функция не может. И не подумайте, что все дело просто в кастинге. ;)
Из всего этого явно следует, что глубокоуважемый не только не делал то, чему поучает других, но даже не читал документацию, которой мне пеняет.
И советую прочитать на досуге стандарты языков си и си+, чтобы не говорить такую
d_n_k писал(а):
12.09.2007 15:46
w<бла-бла-бла> - это stl'ная байда

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

Все же спасибо, что лишний раз меня подвели к bind_textdomain_codeset - когда я сел писать обертку я уже точно знал, что муторный цикл с iconv мне вставлять не нужно... без "перекодировки" все равно не обошлось, но там она уже елементарная, так что то что надо уже напильником обшаркано и почти работает. :happy:

Раз других предложений нет, то, думаю, тему считаем закрытой.
Debian GNU/Linux 4 -- AMD Athlon64 3000+ / Asus 7600GS -- Gnome
Debian GNU/Linux 5 -- Dell (Vostro) 500 (Celeron M560 / iGM965) -- Gnome
Спасибо сказали:
(+ssvda)
Сообщения: 31
ОС: Debian GNU/Linux Etch (only)

Re: Решено: C/C++ wide-литералы и wstrings: как с этим работать УДОБНО? как подружить с gettext?

Сообщение (+ssvda) »

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

Позволю себе, однако, небольшой комментарий. Ваш код

Код: Выделить всё

  #include <iostream>
  int main()  {
    setlocale(LC_ALL, "");

    std::wcout << L"Всем привет!" << std::endl;

    std::wstring wstr;
    std::wcin >> wstr;
    std::wcout << L'[' << wstr << L']' << std::endl;

    return  0;
  }
безусловно рабочий, однако если бы Вы внимательнее почитали стандарт, то очевидно нашли бы там класс std::locale. А в любом потоке нашли бы функцию imbue, которая "вводит" заданную локаль в поток. Установка локали в стиле Си говорит о плохом стиле. Значительно логичнее просто указать потоку с какой локалью работать.

Очень часто приходится встречаться с непониманием по этому поводу. В стандарте сказано, что символьный тип char должен быть одно байтным и прочее (наследие Си). Но также там сказано, что тип wchar_t должен быть достаточным для представления любого символа, переведенного во внутреннее представление (прошу прощения за тавтологию).

Грубо говоря, теоритически компилятор может оперировать с ЛЮБЫМИ представлениями, даже не соответствующими ни одной из известных кодировок (хотя на практике, это конечно не так). Ну да ладно, Вы спросите, а как же тогда быть с внешними данными? Стандарт выделяет как-бы два "мира": "внутренний" и "внешний". И связь между ними обечпечивается одной единственной абстракцией --- потоком. Задача потока взять данные из внешнего мира, перевести их во внутреннее представление и передать программе. Или же наоборот, взять данные во внутреннем представлении, преобразовать их в определенный вформат и передать во внешний мир.

К чему я все это? Ну ведь никто не мешает Вам узнать в какой кодировке опредставленны однобайтные символы в MO файле, так? Читайте "узкие" строки, создавайте локаль, связанную с ними, вводите эту локаль в поток std::wstringstream и выполняйте инициализацию строки таким образом.

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

Гм.. Что-то я болььно много наговорил))). На сим позвольте откланиться...
Спасибо сказали:
Аватара пользователя
serzh-z
Бывший модератор
Сообщения: 8259
Статус: Маньяк
ОС: Arch, Fedora, Ubuntu

Re: Решено: C/C++ wide-литералы и wstrings: как с этим работать УДОБНО? как подружить с gettext?

Сообщение serzh-z »

По-моему ответы, в частности последний, - вполне исчерпывающи. Посему тема закрыта.
Спасибо сказали: