Вопрос или проблема
Я использую X-приложения через SSH-соединение с некоторой машиной. Когда я запускаю X-приложение, скажем, xclock
для простоты, я получаю сообщение в консоли:
Предупреждение: отсутствуют кодировки в преобразовании строки в набор шрифтов
… но приложение работает. Мои локали следующие:
$ locale
LANG=en_US.UTF-8
LC_CTYPE="en_US.UTF-8"
LC_NUMERIC="en_US.UTF-8"
LC_TIME="en_US.UTF-8"
LC_COLLATE="en_US.UTF-8"
LC_MONETARY="en_US.UTF-8"
LC_MESSAGES="en_US.UTF-8"
LC_PAPER="en_US.UTF-8"
LC_NAME="en_US.UTF-8"
LC_ADDRESS="en_US.UTF-8"
LC_TELEPHONE="en_US.UTF-8"
LC_MEASUREMENT="en_US.UTF-8"
LC_IDENTIFICATION="en_US.UTF-8"
LC_ALL=
Теперь я нашел это старое предложение просто установить export LC_ALL=C
. И – это работает, сообщение об ошибке исчезает. Однако я действительно не хочу менять свою локаль таким образом!
Есть ли что-то, что я могу сделать, чтобы избежать ошибки и сохранить свою локаль?
Дополнительная информация:
- X-сервер – интегрированный X-сервер MobaXterm на Windows.
- удаленная машина – SLES GNU/Linux 11 (от SUSE).
Вы правы, не стоит менять свою локаль таким образом! Я нашел похожие предложения и вместо этого решил погрузиться в тему.
Единственная переменная локали, которую вы можете изменить, – это LC_CTYPE=C
(это настройки классификации символов, см. раздел 7 POSIX, Locale для деталей).
Основная проблема здесь, как я считаю, заключается в том, что старые X-программы имеют незначительные проблемы с шрифтами в современных системах с многобайтовыми/многоязычными локалями.
Моя локаль на рабочем столе X Org (Mobaterm использует X Org под капотом) – en_IE.utf
(соответствует файлу en_US.UTF-8/XLC_LOCALE
через /usr/share/X11/locale/locale.dir
). В этом файле XLC_LOCALE есть определения наборов шрифтов и кодировок, и именно наличие некоторых из них (как правило) вызывает предупреждения (в частности, для кириллицы и азиатских кодировок, которые я не использую и для которых у меня нет хорошего охвата шрифтов).
Я получаю несколько ошибок от некоторых программ, например, xfig
:
Предупреждение: отсутствуют кодировки в преобразовании строки в набор шрифтов
Предупреждение: отсутствуют кодировки в преобразовании строки в набор шрифтов
Предупреждение: невозможно загрузить подходящий набор шрифтов
Закомментировав различные нежелательные fsN
и csN
записи, можно это исправить (каждый индекс N определяет соответствующую пару набор шрифтов/кодировка, сохраняйте эту пару, учитывая, что каждая пара находится на ~200 строках друг от друга). Это может повлиять на отображение определенных текстов. Или, установив LC_CTYPE=C
перед запуском xfig
, удаляются все предупреждения.
Предупреждения поступают от XtCvtStringToFontSet()
(libXt), в результате XCreateFontSet()
сообщает о недостающих наборах символов (т.е. наборах символов, используемых/требуемых локалью, но не найденных в шрифте(ах), соответствующих запрашиваемой спецификации).
XCreateFontSet()
возвращает список отсутствующих наборов символов, но libXt не выводит подробностей о запросе или недостающих наборах символов, чтобы помочь вам разобраться. (Я использовал LD_PRELOAD
и обертку .so
для XCreateFontSet()
, чтобы найти виновников, см. ниже.)
Настоящая проблема заключается в том, что шрифт (например, “--helvetica-medium-r-normal–16-––––––“) проверяется для всех кодировок, которые установлены в файле XLC_LOCALE
, и если некоторые не могут быть найдены, тогда вы видите эти предупреждения. Если ничего не найдено, вы также увидите “Предупреждение: невозможно загрузить подходящий набор шрифтов”.
Некоторые исправления:
- установите
LC_CTYPE=C
(или другую “простую” кодировку, напримерen_US
) для проблемных программ - удалите нежелательные пары наборов шрифтов/кодировок из файла XLC_LOCALE в действии (локаль), это вступает в силу без перезагрузки X или рабочего стола
- установите больше шрифтов и кодировок (что-то вроде игры в “молоток по кротам”)
- установите более щедрую спецификацию шрифта приложения (через xrdb или командную строку)
- установите более щедрую спецификацию шрифта по умолчанию (через xrdb)
Возможно, вам потребуются оба последних исправления, поскольку предупреждение может появиться, если какой-либо из шрифтов по умолчанию не соответствует кодировке во время проверки, даже если последующий шрифт подходит.
Ещё одна проблема заключается в том, что некоторые запасные спецификации шрифтов могут продолжать вызывать проблему. В частности, жестко закодированный по умолчанию Xt:
-*-*-*-R-*-*-*-120-*-*-*-*,*
может полностью провалиться, вызывая те же предупреждения. Быстрое тестирование указывает на то, что спецификации шрифтов, которые не содержат семейства (включая только один “*”), могут не соответствовать ничему, хотя ожидалось, что совпадения есть, т.е. с:
xlsfonts -fn "*-*-*-R-*-*-*-120-*-*-*-*"
И добавление завершающего “,*” в качестве полного подстановочного знака может сломать спецификацию шрифта, которая в противном случае работала бы. Наблюдалось на X Org 1.18.3.
Я использую это в своем .Xdefaults
:
XtDefaultFontSet: -*-fixed-medium-r-normal--16-*-*-*-*-*-*-*,-*-fixed-*-*-*--16-*,-*-*-medium-*-*--16-*
что, похоже, делает так, чтобы все работало без сбоев, изменений XLC_LOCALE
не требуется. Этот запасной механизм удачно соответствует каждой запрашиваемой кодировке среди множества шрифтов, которые я каким-то образом накопил…
Вот очень простая обертка (с минимальной проверкой ошибок), которую я использовал, чтобы помочь отслеживать, что запрашивается (так как это часто только определено в исходном коде приложения) и что не находится. Проверено на x86_64 Slackware, другие дистрибутивы/системы могут потребовать небольших настроек.
gcc -fPIC -shared -Wl,-soname,xfontset.so -ldl -o xfontset.so xfontset.c
затем
LD_PRELOAD=$PWD/xfontset.so xfig
чтобы запустить это из директории, в которой вы его скомпилировали.
#define _GNU_SOURCE
#include <stdio.h>
#include <dlfcn.h>
#include <link.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <X11/Xlib.h>
#define DEBUG 1
#define dfprintf(fmt, ...) \
do { if (DEBUG) fprintf(stderr, "[%14s#%04d:%8s()] " fmt, \
__FILE__, __LINE__, __func__,##__VA_ARGS__); } while (0)
// gcc -fPIC -shared -Wl,-soname,xfontset.so -ldl -o xfontset.so xfontset.c
// see X11/Xlib.h
typedef XFontSet XCreateFontSet_fp(
Display *display,
_Xconst char *base_font_name_list,
char ***missing_charset_list_return,
int *missing_charset_count_return,
char **def_string_return
);
static XCreateFontSet_fp *real_XCreateFontSet;
void myinit(void) __attribute__((constructor));
void myinit(void)
{
void *dl;
if ((dl=dlopen(NULL,RTLD_NOW))) {
dfprintf("найден dl по адресу %p ()\n", dl);
real_XCreateFontSet=dlsym(RTLD_NEXT,"XCreateFontSet");
if (!real_XCreateFontSet) dfprintf("ошибка: %s\n",dlerror());
dfprintf("найдена fn() по адресу %p\n", (void *)real_XCreateFontSet);
} else {
dfprintf("dlopen() не удалась...\n");
}
}
// https://www.debian.org/doc/manuals/intro-i18n/ch-examples.en.html
// https://invisible-island.net/xterm/xtoolkit/intrinsics.html
XFontSet XCreateFontSet(Display *display, _Xconst char *base_font_name_list, char ***missing_charset_list_return, int *missing_charset_count_return, char **def_string_return)
{
XFontSet rc;
int fnum,ii;
XFontStruct **xfonts;
char **font_names;
dfprintf("обернуто XCreateFontSet()\n");
dfprintf(" base_font_name_list: <%s>\n",base_font_name_list);
rc=real_XCreateFontSet(display, base_font_name_list, missing_charset_list_return,missing_charset_count_return, def_string_return);
if (*missing_charset_count_return) {
int ii=0;
dfprintf(" #отсутствующие кодировки: %i\n",*missing_charset_count_return);
for (ii=0; ii<*missing_charset_count_return; ii++) {
dfprintf(" %2i: <%s>\n",ii, (*missing_charset_list_return)[ii]);
}
}
if (rc) {
fnum=XFontsOfFontSet(rc,&xfonts,&font_names);
for (ii=0; ii<fnum; ii++) {
dfprintf(" XFontSet[%2i]=<%s>\n",ii,font_names[ii]);
}
} else {
dfprintf("набор шрифтов не найден...\n");
}
return rc;
}
Я хотел бы повысить приоритет варианта #2 в ответе #mr.spuratic, т.е. “отредактировать соответствующий файл XLC_LOCALE”.
Проблема действительно в этом. Исходный код libX11 подразумевает, что у всех пользователей с локалью UTF-8 будут установлены их выбранные шрифты с всеми кодировками по умолчанию!
Тем не менее, ни один из стандартных шрифтов X11 не имеет всех необходимых кодировок для стандартных файлов XLC_LOCALE, например, en_US-UTF-8/XLC_LOCALE
, и большинство людей вне Китая, Японии и Кореи никогда не установят сторонние шрифты с этими кодировками. Это особенно верно, если вы используете, например, одну из локалей en_*.UTF-8
!
Кстати, это произошло еще в 2004 году, когда кто-то (см. исходный код), казалось, произвольно решил переместить выбор iso10646 в файле XLC_LOCALE в конец списка в мастер-коде Xorg. Ранее комментарий гласил:
Мы оставляем наследственные кодировки на данный момент, потому что еще не так много шрифтов ISO10646.
Т.е. изначально структура была такой, что оставлялось место для отката к старым кодировкам до Unicode, ЕСЛИ это необходимо.
Новый порядок предполагает, что кто-то хочет старые кодировки, даже если они установили новый шрифт или несколько шрифтов с кодировкой iso10646, и это кажется просто неправильным, независимо от того, какова могла быть возможная причина для изменения. Я не могу поверить, что это “сломано” так долго! В интернете можно найти много разговоров об этом сообщении об ошибке, и большая часть этого является запутанным, вводящим в заблуждение, а чаще всего просто неправильным.
Во всяком случае, если у вас установлены хорошие шрифты с кодировками iso10646, то весь этот беспорядок со старыми альтернативами следует полностью удалить. С другой стороны, если вы хотите использовать локаль UTF-8, но нужно обратиться к какому-то шрифту с лишь старыми кодировками iso8859-*, то просто переместите разделы iso10646 обратно в верхнюю часть их соответствующих списков.
Кстати, если вы обычный пользователь и не имеете разрешения редактировать необходимые файлы XLC_LOCALE, вы сможете просто скопировать иерархию в свою домашнюю директорию и установить XLOCALEDIR
в окружении, чтобы указать на это место.
Единственная большая проблема заключается в том, что это необходимо сделать везде и в любом месте, где вы хотите запускать любое X11 клиентское приложение, используя локаль UTF-8 (это связано с тем, что проблема заключается в конфигурационном файле для основной библиотеки клиента libX11). Хотя в конечном итоге это не является фатальной ошибкой — только предупреждение о том, что некоторые символы могут не отображаться или могут отображаться неправильно.
Ответ или решение
Решение предупреждения "Warning: Missing charsets in String to FontSet conversion" при использовании X-приложений через SSH
При использовании X-приложений, таких как xclock
, через SSH-соединение, вы можете столкнуться с предупреждением:
Warning: Missing charsets in String to FontSet conversion
Это сообщение может вводить в заблуждение, так как, несмотря на наличие предупреждений, приложения продолжат свою работу. Давайте рассмотрим причины возникновения этой проблемы и возможные решения.
Причины возникновения предупреждения
Данное предупреждение связано с тем, что некоторые старые X-программы имеют проблемы с обработкой шрифтов в современных мультиязычных системах, использующих многобайтовые кодировки, такие как UTF-8. В вашем случае вы используете локаль en_US.UTF-8
, что предполагает наличие поддержки многих символов и кодировок.
Уведомление Missing charsets in String to FontSet conversion
выдается в случае, если запрашиваемые символы не могут быть найдены в установленных шрифтах для данной локали. Это может быть связано с конфигурацией файла XLC_LOCALE
, который управляет отображением шрифтов и кодировок. В большинстве случаев старые установки не имеют необходимых шрифтов с поддержкой всех нужных кодировок, особенно если работа идет с локалями, отличными от языковых пакетов, включающих поддержку юникода.
Решения проблемы
Чтобы устранить предупреждение и при этом сохранить используемую локаль, вы можете рассмотреть следующие варианты:
-
Изменение настроек LC_CTYPE: Вам не обязательно менять всю локаль. Попробуйте временно установить
LC_CTYPE
в значениеC
перед запуском программ:export LC_CTYPE=C xclock
Это может помочь избежать проблемы с кодировками.
-
Редактирование XLC_LOCALE файла: Удаление ненужных пар шрифтов и кодировок из файла
XLC_LOCALE
может кардинально улучшить ситуацию. Для этого:- Найдите файл, соответствующий вашей локали, например,
/usr/share/X11/locale/en_US.UTF-8/XLC_LOCALE
. - Откройте файл с текстовым редактором и удалите строки, связанные с шрифтами и кодировками, которые вам не нужны. Обычно это строки для кириллицы и азиатских языков.
- Найдите файл, соответствующий вашей локали, например,
-
Установка дополнительных шрифтов: Чтобы удовлетворить запросы X-приложений, рассмотрите возможность установки дополнительных шрифтов, которые содержат необходимые кодировки. Это может включать шрифты с поддержкой юникода.
-
Настройка общего шрифта XF86: Используйте команду
xrdb
для настройки базовых шрифтов для X11:xrdb -merge ~/.Xresources
В вашем файле
.Xdefaults
можете указать следующую строку для установки шрифта по умолчанию:XtDefaultFontSet: -*-fixed-medium-r-normal--16-*-*-*-*-*-*-*,-*-fixed-*-*-*--16-*,-*-*-medium-*-*--16-*
-
Локальная настройка окружения: Если у вас нет разрешений для изменения системных файлов, вы можете создать локальную копию нужных файлов в вашей домашней директории. Затем определите переменную окружения
XLOCALEDIR
, указывая путь к вашей копии.
Заключение
Предупреждение Warning: Missing charsets in String to FontSet conversion
связано с тем, что X-приложения не могут найти необходимые шрифты для поддержки запрашиваемых кодировок в вашей локали. Предложенные решения помогут устранить это сообщение об ошибке, сохранив при этом вашу текущую локаль и улучшив опыт использования X-приложений.
Ваше внимание к деталям и готовность оптимизировать настройки системы будут способствовать более приятному и эффективному взаимодействию с X11-приложениями.