Как управлять текстами в проектах и при чем тут i18nЛюбой веб-сайт напичкан текстами, это и длинные описания и короткие название, например, имена полей формы, пунктов меню или названий кнопок. Все это так или иначе где-то описано в коде. Существуют несколько способов все это описать и только один из этих способов правильный. Об этом и поговорим
Самый простой и, возможно, самый распространенный вариант добавлять эти тексты в тех местах где они используются, то есть в шаблонах (и на беке и на фронте). Но за его простотой, скрывается полная дубовость этого варианта, которая с ростом проекта начинает мешать. По пунктам:
* 100% дублирование всех названий. Если у нас есть какое-то поле “Имя”, то оно будет повторено в каждом месте. В крупных проектах это может превращаться в десятки, а то и сотни повторений только для одного названия. А таких не уникальных текстов на сайтах большинство.
* Ручная интерполяция. В тех ситуациях, когда текст содержит динамические части, придется все это закодить руками и тут мы приходим к следующей проблеме
* Учет числа (плюрализация). Часто бывает, что надо писать слово в зависимости от количество элементов: 1 сообщение, 2 сообщения и так далее. Если хардкодить тексты, то эта задача становится проблемой и, часто, говнокодом.
Как минимум, часть проблем может уйти, если вместо текстов вставленных прямо по месту использования, создать словари, например, в json или yaml и дальше использовать их, но даже это решение не справляется с плюрализацией и интерполяцией. Лучше предпочесть специализированное решение и оно есть. Причем, в большинстве бекенд фреймворков оно уже встроено в сам фреймворк (laravel, django, rails и т.п.) это I18n.
I18n работает примерно так, мы описываем файлы с ключами (включая вложенные) и значения (тексты, возможно с интерполяцией)
{
"key_one": "item",
"key_other": "items",
"keyWithCount_one": "`count` item",
"keyWithCount_other": "`count` items"
}
А затем используем в нужном месте программы
i18next.t('key', {count: 0}); // -> "items"
i18next.t('key', {count: 1}); // -> "item"
i18next.t('key', {count: 5}); // -> "items"
i18next.t('key', {count: 100}); // -> "items"
i18next.t('keyWithCount', {count: 0}); // -> "0 items"
i18next.t('keyWithCount', {count: 1}); // -> "1 item"
i18next.t('keyWithCount', {count: 5}); // -> "5 items"
i18next.t('keyWithCount', {count: 100}); // -> "100 items"
Кто-то скажет, погодите, а при чем тут I18n? А вот так. I18n это, на базовом уровне, не инструмент перевода, а инструмент управления текстами. Даже если у вас один язык и другие не планируются, i18n нужно использовать для управления строками. Таким образом полностью решается вопрос дублирования, решается вопрос плюрализация (это базовая фича всех i18n), а еще там есть форматирование:
i18next.t('intlNumber', { val: 1000 });
// --> Some 1,000
И это еще не все. В I18n есть механизм фолбека, то есть когда выбирается какой-то дефолтный текст, если нужно ключа нет. Тоже полезная фича даже без разных языков.
И еще. Во многих бекенд фреймворках свой формат и свои тексты. Фронтенд может создавать свои, а может переиспользовать тексты с бекенда, хотя бы частично. Для этого ко многим фреймворкам понаписаны утилиты, которые позволяют взять бекенд тексты и перекинуть их во фронтенд. Например
https://github.com/fnando/i18n-jsСсылки:
Телеграм |
Youtube |
VKp.s. А как вы работаете с текстами в своих проектах?