Кыргызская локализация в 2013: Unicode, шрифты и клавиатурные раскладки
В 2013 году клиент поставил задачу: государственный портал с поддержкой кыргызского и русского языков. Обязательное требование — работа на кыргызском в браузерах IE8/IE9, которые занимали тогда 55% трафика.
Технически это три независимых задачи, каждая со своими подводными камнями.
Проблема 1: хранение кыргызских символов в MySQL
Кыргызский алфавит включает символы, которых нет в базовой Latin-1 кодировке: ң, ү, ө, ё (и строчные версии). Все они входят в Unicode, но MySQL с настройками по умолчанию хранил их как ?.
Корень проблемы — несоответствие между кодировкой соединения PHP→MySQL и кодировкой таблиц. Даже если таблица в UTF-8, если соединение открыто в latin1, кириллица проходит, а NG (ң) — нет.
-- Проверить текущие настройки
SHOW VARIABLES LIKE 'character%';
SHOW VARIABLES LIKE 'collation%';
-- Что должно быть:
-- character_set_client: utf8
-- character_set_connection: utf8
-- character_set_database: utf8
-- character_set_server: utf8
-- collation_connection: utf8_unicode_ci
-- Создание таблицы с явным указанием кодировки
CREATE TABLE articles (
id INT AUTO_INCREMENT PRIMARY KEY,
title_ky VARCHAR(500) CHARACTER SET utf8 COLLATE utf8_unicode_ci,
title_ru VARCHAR(500) CHARACTER SET utf8 COLLATE utf8_unicode_ci,
body_ky MEDIUMTEXT CHARACTER SET utf8 COLLATE utf8_unicode_ci,
body_ru MEDIUMTEXT CHARACTER SET utf8 COLLATE utf8_unicode_ci,
created_at DATETIME
) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_unicode_ci;
// PHP: устанавливать кодировку сразу после подключения
$db = new PDO('mysql:host=localhost;dbname=mydb;charset=utf8', $user, $pass, [
PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8 COLLATE utf8_unicode_ci",
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
]);
// Или для старого mysql_ API (который ещё использовали в 2013)
mysql_connect($host, $user, $pass);
mysql_query("SET NAMES 'utf8'");
mysql_query("SET CHARACTER SET 'utf8'");
mysql_select_db($dbname);
Важный нюанс: utf8_general_ci и utf8_unicode_ci ведут себя по-разному при сортировке кыргызских строк. unicode_ci использует Unicode Collation Algorithm и сортирует корректнее для нелатинских алфавитов.
Проблема 2: отображение в браузерах
В 2013 году IE8 не поддерживал @font-face для кириллических шрифтов в полном объёме. Кыргызские спецсимволы (ң, ү, ө) отображались корректно только если системный шрифт их содержал — а это зависело от ОС пользователя.
Windows XP + IE8: шрифты Arial, Times New Roman — содержат ң, ү, ө начиная с Windows XP SP2. Проблем нет.
Старые Android-браузеры: стандартный Droid Sans не содержал ң. Символ показывался как квадрат.
Решение: web-safe стек с явным fallback и кастомный шрифт для мобильных:
/* Стек шрифтов для кыргызского контента */
.content-ky {
font-family:
'Noto Sans', /* Google Fonts, поддерживает NG, У с диакритикой */
'Arial Unicode MS', /* Windows, полный Unicode */
'Arial', /* Fallback — есть NG начиная с XP SP2 */
sans-serif;
/* Кыргызский в кириллице — те же direction и language правила что и русский */
direction: ltr;
unicode-bidi: normal;
}
/* Для IE8: не поддерживает @font-face для нестандартных кодировок */
.ie8 .content-ky {
font-family: 'Arial Unicode MS', 'Arial', sans-serif;
}
<!-- HTML: явно указывать lang для браузерного рендеринга и SEO -->
<html lang="ky">
<head>
<meta charset="UTF-8">
<!-- Обязательно: без этого IE интерпретирует кодировку сам -->
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body>
<article lang="ky">
<h1>Кыргызстандын технологиялык өнүгүүсү</h1>
</article>
</body>
</html>
Проблема 3: ввод текста без кыргызской раскладки
Большинство пользователей в 2013 году не имели кыргызской клавиатурной раскладки в системе. Операторы, вводящие контент на кыргызском, использовали русскую раскладку и вставляли спецсимволы вручную.
Мы встроили минималистичную «кыргызскую клавиатуру» в CMS — панель быстрого ввода спецсимволов:
// Панель ввода кыргызских символов для textarea/input
var kyChars = ['ң', 'Ң', 'ү', 'Ү', 'ө', 'Ө'];
function buildKyInputPanel(targetInput) {
var panel = document.createElement('div');
panel.className = 'ky-char-panel';
kyChars.forEach(function(char) {
var btn = document.createElement('button');
btn.type = 'button'; // Важно: не submit
btn.textContent = char;
btn.title = 'Вставить: ' + char;
btn.onclick = function() {
insertAtCursor(targetInput, char);
};
panel.appendChild(btn);
});
return panel;
}
function insertAtCursor(input, text) {
var start = input.selectionStart;
var end = input.selectionEnd;
var val = input.value;
input.value = val.substring(0, start) + text + val.substring(end);
input.selectionStart = input.selectionEnd = start + text.length;
input.focus();
}
// Инициализация для всех кыргызских полей
document.querySelectorAll('[data-lang="ky"]').forEach(function(input) {
var panel = buildKyInputPanel(input);
input.parentNode.insertBefore(panel, input.nextSibling);
});
.ky-char-panel {
display: flex;
gap: 4px;
margin-bottom: 4px;
}
.ky-char-panel button {
padding: 4px 8px;
font-size: 16px;
border: 1px solid #ccc;
background: #f9f9f9;
cursor: pointer;
font-family: 'Arial Unicode MS', Arial, sans-serif;
}
Полнотекстовый поиск по кыргызскому тексту
MySQL FULLTEXT в utf8_unicode_ci работал корректно для кириллических символов, но NG (ң) и другие кыргызские спецсимволы попадали в стоп-слова или не индексировались правильно в ранних версиях MySQL 5.1.
Решение: нормализация перед индексацией — заменять спецсимволы на их эквиваленты для поискового индекса:
/**
* Нормализация кыргызского текста для поискового индекса.
* Спецсимволы маппятся на ближайшие фонетические эквиваленты.
* Используется ТОЛЬКО для индекса — оригинальный текст хранится без изменений.
*/
function normalizeKyForSearch(string $text): string {
return strtr(mb_strtolower($text, 'UTF-8'), [
'ң' => 'ng',
'ү' => 'u',
'ө' => 'o',
'ё' => 'yo',
]);
}
// При индексации: сохраняем оригинал + нормализованную версию
$article->body_ky_search = normalizeKyForSearch($article->body_ky);
// При поиске: нормализуем запрос так же
$searchQuery = normalizeKyForSearch($userInput);
Что изменилось с тех пор
Современные браузеры, Android и iOS нативно поддерживают все Unicode-символы. Google Fonts включает Noto Sans со всеми кыргызскими символами. Полнотекстовый поиск в PostgreSQL и Elasticsearch работает с кыргызским без дополнительной настройки.
Но принцип остался: при работе с нелатинскими языками явно указывай кодировку на каждом уровне стека — от HTTP-заголовков до collation базы данных. Одного UTF-8 в HTML недостаточно, если соединение с БД или HTTP-сервер интерпретирует кодировку иначе.