Text Resources And Encoding
Проблема
В кодовой базе много строковых констант находится прямо в C++ файлах. Часть файлов исторически живет в CP1251, часть уже в UTF-8, часть может иметь смешанные окончания строк.
Это создает проблемы:
- сложнее работать из современных инструментов;
- легко сломать кодировку при правке;
- сложно переиспользовать тексты в web-клиенте;
- невозможно нормально локализовать UI;
- один и тот же текст приходится искать по коду.
Цель
Все пользовательские тексты должны постепенно переехать из C++ в отдельные resource-файлы.
C++ должен оперировать ключами:
tr("menu.balance.caption")
А не строками:
_T("Баланс")
Кодировки
Правило для новых файлов:
- документация: UTF-8;
- JSON web protocol: UTF-8;
- новые resource-файлы: UTF-8;
- старые CP1251 файлы не перекодируются массово без отдельной задачи;
- точечные правки в старых CP1251 файлах делаются без изменения кодировки файла.
Пока допускается, что legacy runtime может читать CP1251-ресурсы. Но целевая модель для web/headless - UTF-8.
Resource Files
Предлагаемый формат для новых текстов:
resources/
ru/
menu.json
controls.json
errors.json
Пример resources/ru/menu.json:
{
"menu.balance.caption": "Баланс",
"menu.cashflow.caption": "ДДС",
"menu.profitloss.caption": "ОПиУ",
"menu.settings.caption": "Настройки"
}
Для Win32-слоя можно добавить адаптер:
string text = textResources.get("menu.balance.caption");
Для web-клиента тот же ключ может уходить в JSON формы:
{
"id": "Balance",
"captionKey": "menu.balance.caption",
"caption": "Баланс"
}
Что выносить первым
В первую очередь выносим:
- подписи menu item-ов;
- подписи кнопок;
- заголовки форм;
- тексты ошибок;
- подсказки и hint-ы;
- тексты системных popup-меню.
Не выносим в первую очередь:
- технические имена классов;
- XML tag names;
- внутренние enum/string protocol values;
- имена обработчиков типа
OnBalanceClick.
Menu Example
XML может временно содержать готовый caption:
<Item Caption="Баланс" Name="Balance"/>
Целевой вариант:
<Item CaptionKey="menu.balance.caption" Name="Balance"/>
Runtime:
CaptionKey -> TextResources -> Caption
Web:
{
"type": "menu.item",
"id": "Balance",
"captionKey": "menu.balance.caption",
"caption": "Баланс"
}
Compatibility Plan
Переход должен быть постепенным:
- Добавить
TextResourcesservice. - Научить
menuчитатьCaptionKey. - Если
CaptionKeyзадан, брать текст из ресурсов. - Если
CaptionKeyне задан, использовать legacyCaption. - Для новых форм использовать только
CaptionKey. - Старые CP1251 C++ строки убирать по мере касания файлов.
Development Rules
Для новых изменений:
- Не добавлять новые пользовательские тексты прямо в C++ без причины.
- Если текст нужен Win32 и Web, он должен быть resource key.
- Если правится CP1251 файл, не перекодировать весь файл.
- Markdown-документацию писать в UTF-8.
- JSON-ресурсы писать в UTF-8.
Open Questions
- Нужен ли один общий namespace ключей или namespace по модулям.
- Где хранить клиентские переопределения текстов.
- Нужна ли hot reload загрузка ресурсов без перезапуска сервера.
- Как версионировать resource-файлы вместе с приложениями.