LINUX.ORG.RU

Написал статью «Как жить если у вас юникод»

 ,


5

4

Собственно, сабж. Статья про то самое, что мы с Eddy_Em не могли осилить в прежние времена. В этом году я это, внезапно, осилил. Ну и написал статью.

https://saahriktu.ru/pdf/kak_jit_esli_u_vas_yunikod.pdf

★★★★★

Ответ на: комментарий от ComradeDOS

Комбинирующий символ следует за буквой и поэтому и «й» попадает под шаблон «и*».

Он не следует за буквой, он часть буквы. Идея, что комбинирующие символы могут жить своей жизнью, самая безумная из тех, на которые я натыкался.

А потом при поиске по букве «ш» будет находится также и «щ»? Ведь в ней эта «ш» «присутствует».

monk ★★★★★
()
Ответ на: комментарий от Forum0888

В Windows wchar является по существу кодом символа, поэтому API для анализа строк весьма не сложно и эффективно в отличии от UTF.

И поэтому половина программ для Windows ломаются, как только попадает символ, не поместившийся в wchar.

monk ★★★★★
()
Ответ на: комментарий от monk

В Windows кодовые страницы для UTF16LE содержат лишь данные о символах кодовой страницы.
Поэтому ничего не ломается.
По существу это а-ля code page для UNICODE.
И ещё в Windows свои кодовые страницы.

Forum0888
()
Последнее исправление: Forum0888 (всего исправлений: 2)
Ответ на: комментарий от ComradeDOS

Всё зависит от того как интерпретировать пользовательский ввод.

Локаль ru_RU.UTF-8

А нет ли там флага, который позволяет менять поведение на нужное?)

Я не нашёл.

monk ★★★★★
()
Ответ на: комментарий от Forum0888

Всего лишь буквальная трактовка «в Windows wchar является по существу кодом символа, поэтому API для анализа строк весьма не сложно и эффективно в отличии от UTF».

Если анализировать правильно, то уже неважно, символ из массива байт состоит или массива wchar.

monk ★★★★★
()
Ответ на: комментарий от monk

Посмотрю ради интереса CRT Visual Studio ...
Скорее всего в кодовых страницах Windows нет «комбинированных символов».
У немцем к примеру для обычной code page, в строке некоторые символы трактуются как несколько ... (если не ошибаюсь).
Вообщем-то для разных стран имеются «заморочки» с кодовыми страницами (тема интересная).

Поиск

error+with+output+column+Text+was+truncated+or+one+or+more+characters+had+no+match+in+the+code+page

Forum0888
()
Последнее исправление: Forum0888 (всего исправлений: 4)
Ответ на: комментарий от Forum0888

В кодовых страницах Windows все символы имеют размер 16 бит.

Кодовая страница 65001. Кодепоинт юникода может быть из двух wchar.

https://habr.com/ru/articles/485148/#6

А символ юникода состоит из произвольного количества кодепоинтов.

monk ★★★★★
()
Ответ на: комментарий от monk

wchar это а-ля поддержка code page в UNICODE (и не более того).

https://en.wikipedia.org/wiki/Windows_code_page
https://www.aivosto.com/articles/charsets-codepages-windows.html

В Windows 10 уже имеется поддержка UTF-8.

Впрочем в Windows кроме code page имеется API для использования других видов символов.

Forum0888
()
Последнее исправление: Forum0888 (всего исправлений: 4)

Статья безграмотная. Как же мне бомбит с того, что одни и те же мифы о юникоде уже два десятилетия все, кому не лень, долдонят.

Первое. В нормальных ОС setlocale вызывать не нужно никогда, потому что стандартная библиотека получает настройки локали из окружения (из переменных LOCALE и LC_*).

Второе. wchar_t использовался тогда, когда считалось, что 65536 код-поинтов хватит всем. Сейчас кодпоинтов гораздо больше, а в качестве стандарта хранения юникода победил, слава б-гу, UTF-8, который великолепно себя чувствует внутри обычных char*.

Третье. Соответственно, нужды в т.н. wide chars в 2k23 нет никакой.

Четвёртое. Весь вывод является юникодным, потому что UTF-8 (который, я напомню, де-факто стандарт хранения текста) победил. ASCII-шный текст из одних только символов английского алфавита — подмножество корректного UTF-8. Про wprintf и другие w-функции давно пора забыть, как про страшный сон.

Пятое. Ну вы поняли, за использование wchar_t нужно больно бить по пальцам металлической линейкой.

Шестое. Если нужно содержательно работать со строками в UTF-8, т.е. не как с массивом байтов, а как с массивом код-пойнтов, каждый из которых может занимать больше одного байта, есть целый ряд альтернатив:

  • функции из Glib с префиксом g_utf8_
  • libicu
  • header-only либа sheredom utf8.h
  • GNU libunistring

В качестве бонуса: префикс 0b доступен в стандарте C23, который ещё официально не принят, а case ranges — нестандартное расширение GNU.

lockie
()
Ответ на: комментарий от lockie

В статье по каждому пункту есть пояснения. В Си классические строковые функции оставлены однобайтными, их логику никто не менял. Им можно скормить строки в однобайтных кодировках и результат будет ровно такой же как и в 1980-х. Для работы с юникодом в ANSI C ввели ряд других функций, которые работают с wchar_t*. Всякие сторонние библиотеки наподобие ICU не входят ни в какие стандарты. А wchar_t* входит в ANSI C.

И безграмотны как раз те, кто путают кодировки (UTF-8, UTF-16 и UTF-32) и типы char* и wchar_t*.

Без setlocale() Сишные программы не работают как положено ни с KOI8-R в ncurses, ни c юникодом. Просто потому, что они не читают все переменные окружения на старте. И их нужно принудительно просить их прочитать если это нужно. Если Вы считаете иначе, то, скорее всего, Вы просто какие-то книжки по Си читали, но так и не добрались до написания кода в GNU/Linux. В винде оно может иначе работать, не проверял. У меня и винды-то нет. А вот в GNU/Linux всё работает именно так, как написано в статье.

saahriktu ★★★★★
() автор топика
Последнее исправление: saahriktu (всего исправлений: 1)
Ответ на: комментарий от lockie

wchar_t использовался тогда, когда считалось, что 65536 код-поинтов хватит всем. Сейчас кодпоинтов гораздо больше

wchar_t в GNU/Linux позволяет хранить один из 2147483648-ми кодепоинтов, если что.

saahriktu ★★★★★
() автор топика
Ответ на: комментарий от monk

Буквы с диакритическими знаками сочетаются выделением символа с диакритикой.

Так было в ISO 10646, но абсурдность такого подхода стала настолько очевидна, что от в Юникоде от нее отказались.

Какой гений решил, что порядок сортировки строк должен определяться национальностью пользователя?

А причем тут Юникод? Таблицы сортировки существовали задолго до него.

В современном Windows 10 в блокноте если ввести «й» и нажать Backspace, останется буква «и».

В какой версии?

Но в юникоде символов слишком много, чтобы перебрать все вручную

Описываются правила, применимые к конкретному языку.

pasquale
()
Ответ на: комментарий от pasquale

абсурдность такого подхода стала настолько очевидна, что от в Юникоде от нее отказались

Можно ссылку на обсуждение, из которого следовала абсурдность? По факту, именно из-за этого отказа мы имеем 4 нормализации, ни одна из которых нормально не работает, и кучу программного обеспечения, которое не умеет работать с комбинированными символами.

Пока мне больше кажется, эта «абсурдность» имеет те же, корни, что и абсурдность простого HTML, которая привела к тому, что современный браузер намного сложнее современной операционной системы (в стандартах w3c 114 миллионов слов и ежегодно добавляется ещё по 4 миллиона, а во всех RFC + POSIX всего 60 миллионов).

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

А причем тут Юникод? Таблицы сортировки существовали задолго до него.

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

В какой версии?

22H2 (сборка 19045.3342)

Описываются правила, применимые к конкретному языку.

Это опять та же проблема: «мой софт поддерживает юникод, но работает только английский, русский и китайский; описания ошибок при обработке арабских, тайских и индийских строк не принимаются».

monk ★★★★★
()
Ответ на: комментарий от monk

При том, что, язык текста должен зависеть от текста, а не от читающего этот текст пользователя.

Порядок сортировки не имеет прямого отношения к языку текста. Мне, например, хочется видеть слова на букву Ä среди слов с буквой A, а на букву Y - между X и Z. Русская локаль и дает такой порядок. Если пользователю привычней другой порядок, то он задает подходящую локаль.

22H2 (сборка 19045.3342)

У меня буква й удаляется целиком.

«мой софт поддерживает юникод, но работает только английский, русский и китайский

Нет. Если вам нужно считать æ за две буквы и допускать legacy-символы для лигатур во входных данных - это ваши личные требования, и никакого отношения к Юникоду они не имеют. Правила обработки по умолчанию применяются ко всем символам и вполне достаточны.

pasquale
()
Ответ на: комментарий от lockie

Первое. В нормальных ОС setlocale вызывать не нужно никогда, потому что стандартная библиотека получает настройки локали из окружения (из переменных LOCALE и LC_*).

Дальше можно не читать.

yuripv79
()
Ответ на: комментарий от pasquale

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

А если мне хочется, чтобы шведские слова были по шведскому алфавиту, то мне только шведские региональные настройки на всё приложение ставить и терпеть Ё перед А?

У меня буква й удаляется целиком.

Это не та. Скопируй эту: й

Правила обработки по умолчанию применяются ко всем символам и вполне достаточны.

Ну да. Только половина программ не находит строку, если символ в ней составной.

Вот пример про зависимость обработки от СУБД: https://habr.com/ru/articles/262679/#comment_22619420

Если вам нужно считать æ за две буквы и допускать legacy-символы для лигатур во входных данных - это ваши личные требования, и никакого отношения к Юникоду они не имеют.

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

monk ★★★★★
()
Ответ на: комментарий от pasquale

Если пользователю привычней другой порядок, то он задает подходящую локаль.

А ещё проблема с изменением регистра. Запись прописными «располагалось в Берлине по адресу Prinz-Albrecht-Straße» выдаёт в русской локали «РАСПОЛАГАЛОСЬ В БЕРЛИНЕ ПО АДРЕСУ PRINZ-ALBRECHT-STRAßE», а должно быть «РАСПОЛАГАЛОСЬ В БЕРЛИНЕ ПО АДРЕСУ PRINZ-ALBRECHT-STRASSE». Но для этого надо менять локаль на немецкую.

monk ★★★★★
()
Ответ на: комментарий от monk

Но для этого надо менять локаль на немецкую.

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

Здесь проблема не ITU, а в том, что нет удобного класса, который мог бы работать с строками как с объектами
(понятно, что объект должен иметь свойства слова или нескольких слов).

Без такого класса пишется обычная «каша-малаша».

----------------------------------------------
Хороший пример вы привели.
Не встречал документа в котором было разъяснены особенности кодировок для разных языков (а их немало).

Посмотрю исходники LibreOffice на предмет того, учитывается ли в функциях для работы с текстом особенности национальных кодировок.

Да и исходники Linux нужно будет посмотреть.

Forum0888
()
Последнее исправление: Forum0888 (всего исправлений: 7)
Ответ на: комментарий от monk

На всякий случай отмечу, что лигатурам, вообще говоря, не место в Unicode (те, что есть, введены только для совместимости с существующими 8-битными кодировками). Лигатура – свойство шрифта, которым отображается текст. https://unicode.org/faq/ligature_digraph.html

TeopeTuK ★★★★
()
Ответ на: комментарий от TeopeTuK

На всякий случай отмечу, что лигатурам, вообще говоря, не место в Unicode

В общем, по разъяснению, можно считать, что если пользователь воткнул лигатуру символом юникода, то «сам виноват».

Они бы ещё предложили какой-нибудь инструмент по убиранию лигатур. Вот человек спрашивал, что делать: https://superuser.com/questions/669130/double-latin-letters-in-unicode-ligatures#comment2285913_669150

Предложили «перебери сам всю сотню тысяч символов».

monk ★★★★★
()
Ответ на: комментарий от TeopeTuK

Тут могу согласиться, убирать кем-то вставленные лигатуры неудобно.

https://question-it.com/questions/11686162/ligatury-shriftov-tcpdf-anglijskij Лигатуры шрифтов tcpdf (английский)?

...

Поиск типа «freetype лигатуры».

Forum0888
()
Ответ на: комментарий от monk

Да, много разного нужного API пока никто не разработал ...

https://blog2k.ru/archives/3734 Используем FreeType для вывода строки

Forum0888
()
Последнее исправление: Forum0888 (всего исправлений: 1)
Ответ на: комментарий от monk

Я не очень понимаю, почему и в каком смысле «приплыли». Каким образом текст отображается для его восприятия человеком, дело десятое. Лигатура вполне может быть реализована как отдельный символ в шрифте. Если при этом, например, copy&paste из показанного текста восстанавливает исходные символы, то этого вполне достаточно для удобной работы с текстом.

TeopeTuK ★★★★
()
Ответ на: комментарий от Forum0888

Ещё.

Да, много разного нужного API пока никто не разработал ...

https://blog2k.ru/archives/3734 Используем FreeType для вывода строки

Да и для работы с шрифтами ещё много удобного API не разработано. В Linux трёшка библиотек есть, но ИМХО это лучше чем «ничего».

К примеру нужно мне вывести символ с подчёркиванием c использование шрифта https://fonts-online.ru/fonts/times-new-roman

Какой файл содержит необходимый шрифт (а их несколько)?
В Linux имеются несколько библиотек, которые имеют метаданные о шрифтах и как-то в чём-то помогают.
Но нужен удобный API, который такого рода вопросы нативно решает и много упрощает код.
Так это всего лишь один из примеров ...

Потому-то и сделал форк freetype.
Его ещё «пилить» и «пилить».

Forum0888
()
Последнее исправление: Forum0888 (всего исправлений: 4)
Ответ на: комментарий от TeopeTuK

Если при этом, например, copy&paste из показанного текста восстанавливает исходные символы, то этого вполне достаточно для удобной работы с текстом.

А как он восстановит? Такой «нормализации», чтобы убирала лигатуры, но не ломала всё остальное, не предусмотрено.

monk ★★★★★
()
Ответ на: комментарий от saahriktu

Им можно скормить строки в однобайтных кодировках и результат будет ровно такой же как и в 1980-х.

Я вам более того скажу, в них можно скормить строки в юникоде.

Для работы с юникодом в ANSI C ввели ряд других функций, которые работают с wchar_t*

А через десяток лет выяснилось, что wchar_t — это неадекватный способ хранения юникода и обычный char с этим прекрасно справляется, если используется кодировка юникода UTF-8.

те, кто путают кодировки (UTF-8, UTF-16 и UTF-32) и типы char* и wchar_t*.

Где я писал, что это одно и то же?

Без setlocale() Сишные программы не работают как положено ни с KOI8-R

Вы ещё пожалуйтесь, что ваша программа на C не работает как положено на БК0010. Нужно современными реалиями жить, а не тащить на горбу всякий шлак из прошлого.

lockie
()
Ответ на: комментарий от monk

Мне представляется, что при выводе текста на экран/куда-либо не нужно забывать что это за текст. Вот пример: https://sgolovan.nes.ru/tmp/liga.pdf (видна лигатура, копируется вполне нормальное ffi).

TeopeTuK ★★★★
()
Ответ на: комментарий от Aswed

Раз уж по мертвым языкам пошел, расскажи как с utf в коболе?

Отлично.

01 u1 pic u(10).  *> fixed character-length UTF-8 data item holding 10 UTF-8 characters (40 bytes reserved)
01 u2 pic uuuu.   *> fixed character-length UTF-8 data item holding 4 UTF-8 characters (16 bytes reserved)
monk ★★★★★
()
Ответ на: комментарий от TeopeTuK

Мне представляется, что при выводе текста на экран/куда-либо не нужно забывать что это за текст.

Так здесь TeX отдельно сформировал картинку лигатуры, а отдельно текстовое представление. Браузер тоже лигатуры сам формирует (если атрибутом не запрещено). А вот если просто использовать freetype, то придётся все лигатуры обрабатывать до вывода самостоятельно.

monk ★★★★★
()
Ответ на: комментарий от Forum0888

Ещё

Разработаю кроссплатформенную метадата базу для шрифтов и localе и конечно API для работы с строками и шрифтами, использующие эти метаданные.
Можно будет использовать в любой ОС.

Шутка

И в Haiku непременно.

Forum0888
()
Последнее исправление: Forum0888 (всего исправлений: 1)