После прохождения курса JS: Архитектура фронтенда я решил вернуться к упражнению по организации текстов интерфейса и доработать его так, чтобы создавать массив с названием добавленных языков не требовалось, а данные автоматически загружались из файловой системы.
- Как перенести упражнение на компьютер
- Приступаю к проекту
- Ложный путь
- Новая идея
- Добавление примера
- Валидация
- Загрузка новых локалей
- Итог
Как перенести упражнение на компьютер
Кажется, что сделать это легко - достаточно скопировать код и установить нужные библиотеки. Но, к сожалению, реальность полна разочарований.
Webpack
Обязательная библиотека в этом проекте — Webpack. Благодаря ей вы не будете ограничены функцией импорта модулей. Кроме того, вам не придется подключать десятки скриптов к HTML-странице. Webpack соберет весь код в один файл и упростит подключение других библиотек. Для установки Webpack можно воспользоваться этой инструкцией.
После настройки Webpack можно просто скопировать код, устанавливать нужные библиотеки и начинать экспериментировать.
Приступаю к проекту
Первым делом я перенёс верстку в отдельный HTML-файл и подключил Bootstrap к JS-файлу. затем переписал код так, чтобы он соответствовал модели MVC (или моему ложному пониманию данной модели). Вынес модель в отдельный файл с инициализацией, который запускается только один раз и в котором создается новый инстанс i18next.
// init.js
export const i18n = i18next.createInstance();
export default async () => {
await initI18n(i18n); // инициализация i18next;
state = {
// модель приложения
};
return state;
};
Затем перенес все функции рендера в файл view.js, а все контроллеры — в app.js.
Ложный путь
Следующим шагом я попотался сделать так, чтобы код читал директорию и выводил массив файлов. Идея была в том, чтобы избавиться от массива ['en', 'ru']
, который должен был создаваться автоматически.
Тогда я не знал, что Node.JS-модули File System не работают в браузере. Тогда я нашёл полифил browserify-fs, но он не помог решить проблему. Получилось так, что внутри localhost я создал директорию, куда сначала записывал файлы, а затем чистал их, что совершенно бессмысленно.
Новая идея
Затем я решил попробовать сделать так, чтобы дополнительный язык мог добавить не программист, имеющий доступ к файлам проекта, а любой пользователь. Для этого я создал форму загрузки файла и переместил textarea
в аккордеон, чтобы не перегружать интерфейс.
Кажется, что осталось только реализовать добавление новых локалей в i18next, но это не так. Я знаю, как должен выглядеть файл с текстами, знаю его структуру, а что делать пользователю?
Добавление примера
На экран нужно выводить пример JSON-файла, но как реализовать вывод?
Модальное окно добавить просто: оставалось понять, как размещать текст внутри него. У меня был готовый файл example.json с инструкцией на немецком языке. Можно было просто скопировать текст из него в модальное окно, но это неудобно - при изменении текста содержимое модального окна придется менять вручную. Поэтому выброл другой способ:
- Импортирую JSON-файл, который Webpack конвертирует в обычный JS-объект
- Конвертирую объект обратно в JSON
- Добавляю текст в тег
pre
для сохранения форматирования.
P.S. Если хотите сохранить отступы, то конвертировать нужно так:
JSON.stringify(example, null, ' ');
Валидация
Самая важная и самая сложная часть проекта. Валидацию решил делать асинхронной. Что требовалось проверять?
- Поле не должно быть пустым
- Только латинские буквы в дополнительных полях ввода
- Файл формата JSON
- Размер файла до 2000 Б
- Правильность JSON-данных.
Первые пункты довольно просты, а последнему требуется уделить отдельное внимание. Отсановимся на нем подробнее.
Валидация JSON
Первым делом нужно быть проверить, что JSON — это действительно JSON. Выбрал проверку парсингом данных: если тест проходит, значит, все в порядке. Еще один тест проверяет наличие необходимых для i18next ключей. В случае ошибки в логе выводится список недостающих ключей.
Локализация ошибок
Для локалицзации yup через i18next я использовал setLocale()
. Но это позволяет получить переводы только для стандартных случаев, но не для тестов получилось добавить переводы только для каких-то стандартных случаев, но не для тестов.
Итоговую схему валидации можно посмотреть в файле schema.js.
Загрузка новых локалей
После завершения подготовительных работ можно приступить к основной функции проекта – добавлению языков.
Для загрузки используется метод addResourceBundle()
библиотеки i18next. После загрузки я обновляю ресурсы с помощью метода reloadResources()
.
Код этой функции представлен в файле handleAddLanguage.js.
Toast
Toast отвечает за всплывающую ошибку в случае, если не удалось загрузить ту или иную локаль С помощью Bootstrap JavaScript реализовать эту функцию было достаточно просто — тем более, что модельное окно управлялось с помощью Bootstrap.
Дополнения
- Кнопка «Копировать». Поскольку копировать текст из модального окна не очень удобно (особенно на телефоне), добавил кнопку копирования примера в буфер обмена.
- Блокировка полей. После успешной загрузки файла кнопка блокируется на пять секунд чтобы нельзя было загрузить что-то еще. Кнопка «копировать в буфер обмена» блокируется на 5 секунд, чтобы пользователь не могу загрузить что-то еще. По той же схеме кнопка блокируется в случае ошибке валидации и отправки данных.
Итог
Работа над проектом заняла у меня гораздо больше времени, чем я рассчитывал. Конечно, на это сильно повлияло то, что я каждый раз добавлял что-то ещё. Зато я узнал много нового: например, как читать файлы или работать с буфером обмена, а также библиотеками yup и i18next, которые пригодятся в работе над RSS агрегатором.
Проект я обязательно добавлю в резюме, а вы можете его посмотреть, перейдя поссылке. А веб версию здесь.