0 added
0 removed
Original
2026-01-01
Modified
2026-02-26
1
<p>После прохождения курса<a>JS: Архитектура фронтенда</a>я решил вернуться к упражнению по организации текстов интерфейса и доработать его так, чтобы создавать массив с названием добавленных языков не требовалось, а данные автоматически загружались из файловой системы.</p>
1
<p>После прохождения курса<a>JS: Архитектура фронтенда</a>я решил вернуться к упражнению по организации текстов интерфейса и доработать его так, чтобы создавать массив с названием добавленных языков не требовалось, а данные автоматически загружались из файловой системы.</p>
2
<h2>Как перенести упражнение на компьютер</h2>
2
<h2>Как перенести упражнение на компьютер</h2>
3
<p>Кажется, что сделать это легко - достаточно скопировать код и установить нужные библиотеки. Но, к сожалению, реальность полна разочарований.</p>
3
<p>Кажется, что сделать это легко - достаточно скопировать код и установить нужные библиотеки. Но, к сожалению, реальность полна разочарований.</p>
4
<h3>Webpack</h3>
4
<h3>Webpack</h3>
5
<p>Обязательная библиотека в этом проекте -<a>Webpack</a>. Благодаря ей вы не будете ограничены функцией импорта модулей. Кроме того, вам не придется подключать десятки скриптов к HTML-странице. Webpack соберет весь код в один файл и упростит подключение других библиотек. Для установки Webpack можно воспользоваться<a>этой инструкцией</a>.</p>
5
<p>Обязательная библиотека в этом проекте -<a>Webpack</a>. Благодаря ей вы не будете ограничены функцией импорта модулей. Кроме того, вам не придется подключать десятки скриптов к HTML-странице. Webpack соберет весь код в один файл и упростит подключение других библиотек. Для установки Webpack можно воспользоваться<a>этой инструкцией</a>.</p>
6
<p>После настройки Webpack можно просто скопировать код, устанавливать нужные библиотеки и начинать экспериментировать.</p>
6
<p>После настройки Webpack можно просто скопировать код, устанавливать нужные библиотеки и начинать экспериментировать.</p>
7
<h2>Приступаю к проекту</h2>
7
<h2>Приступаю к проекту</h2>
8
<p>Первым делом я перенёс верстку в отдельный HTML-файл и подключил Bootstrap к JS-файлу. затем переписал код так, чтобы он соответствовал модели MVC (или моему ложному пониманию данной модели). Вынес модель в отдельный файл с инициализацией, который запускается только один раз и в котором создается новый инстанс i18next.</p>
8
<p>Первым делом я перенёс верстку в отдельный HTML-файл и подключил Bootstrap к JS-файлу. затем переписал код так, чтобы он соответствовал модели MVC (или моему ложному пониманию данной модели). Вынес модель в отдельный файл с инициализацией, который запускается только один раз и в котором создается новый инстанс i18next.</p>
9
<p>Затем перенес все функции рендера в файл view.js, а все контроллеры - в app.js.</p>
9
<p>Затем перенес все функции рендера в файл view.js, а все контроллеры - в app.js.</p>
10
<h2>Ложный путь</h2>
10
<h2>Ложный путь</h2>
11
<p>Следующим шагом я попотался сделать так, чтобы код читал директорию и выводил массив файлов. Идея была в том, чтобы избавиться от массива ['en', 'ru'], который должен был создаваться автоматически.</p>
11
<p>Следующим шагом я попотался сделать так, чтобы код читал директорию и выводил массив файлов. Идея была в том, чтобы избавиться от массива ['en', 'ru'], который должен был создаваться автоматически.</p>
12
<p>Тогда я не знал, что Node.JS-модули File System не работают в браузере. Тогда я нашёл полифил<a>browserify-fs</a>, но он не помог решить проблему. Получилось так, что внутри localhost я создал директорию, куда сначала записывал файлы, а затем чистал их, что совершенно бессмысленно.</p>
12
<p>Тогда я не знал, что Node.JS-модули File System не работают в браузере. Тогда я нашёл полифил<a>browserify-fs</a>, но он не помог решить проблему. Получилось так, что внутри localhost я создал директорию, куда сначала записывал файлы, а затем чистал их, что совершенно бессмысленно.</p>
13
<h2>Новая идея</h2>
13
<h2>Новая идея</h2>
14
<p>Затем я решил попробовать сделать так, чтобы дополнительный язык мог добавить не программист, имеющий доступ к файлам проекта, а любой пользователь. Для этого я создал форму загрузки файла и переместил textarea в<a>аккордеон</a>, чтобы не перегружать интерфейс.</p>
14
<p>Затем я решил попробовать сделать так, чтобы дополнительный язык мог добавить не программист, имеющий доступ к файлам проекта, а любой пользователь. Для этого я создал форму загрузки файла и переместил textarea в<a>аккордеон</a>, чтобы не перегружать интерфейс.</p>
15
<p>Кажется, что осталось только реализовать добавление новых локалей в i18next, но это не так. Я знаю, как должен выглядеть файл с текстами, знаю его структуру, а что делать пользователю?</p>
15
<p>Кажется, что осталось только реализовать добавление новых локалей в i18next, но это не так. Я знаю, как должен выглядеть файл с текстами, знаю его структуру, а что делать пользователю?</p>
16
<h2>Добавление примера</h2>
16
<h2>Добавление примера</h2>
17
<p>На экран нужно выводить пример JSON-файла, но как реализовать вывод?</p>
17
<p>На экран нужно выводить пример JSON-файла, но как реализовать вывод?</p>
18
<p><a>Модальное окно</a>добавить просто: оставалось понять, как размещать текст внутри него. У меня был готовый файл<a>example.json</a>с инструкцией на немецком языке. Можно было просто скопировать текст из него в модальное окно, но это неудобно - при изменении текста содержимое модального окна придется менять вручную. Поэтому выброл другой способ:</p>
18
<p><a>Модальное окно</a>добавить просто: оставалось понять, как размещать текст внутри него. У меня был готовый файл<a>example.json</a>с инструкцией на немецком языке. Можно было просто скопировать текст из него в модальное окно, но это неудобно - при изменении текста содержимое модального окна придется менять вручную. Поэтому выброл другой способ:</p>
19
<ul><li>Импортирую JSON-файл, который Webpack конвертирует в обычный JS-объект</li>
19
<ul><li>Импортирую JSON-файл, который Webpack конвертирует в обычный JS-объект</li>
20
<li>Конвертирую объект обратно в JSON</li>
20
<li>Конвертирую объект обратно в JSON</li>
21
<li>Добавляю текст в тег pre для сохранения форматирования.</li>
21
<li>Добавляю текст в тег pre для сохранения форматирования.</li>
22
</ul><p>P.S. Если хотите сохранить отступы, то конвертировать нужно так:</p>
22
</ul><p>P.S. Если хотите сохранить отступы, то конвертировать нужно так:</p>
23
<h2>Валидация</h2>
23
<h2>Валидация</h2>
24
<p>Самая важная и самая сложная часть проекта. Валидацию решил делать асинхронной. Что требовалось проверять?</p>
24
<p>Самая важная и самая сложная часть проекта. Валидацию решил делать асинхронной. Что требовалось проверять?</p>
25
<ul><li>Поле не должно быть пустым</li>
25
<ul><li>Поле не должно быть пустым</li>
26
<li>Только латинские буквы в дополнительных полях ввода</li>
26
<li>Только латинские буквы в дополнительных полях ввода</li>
27
<li>Файл формата JSON</li>
27
<li>Файл формата JSON</li>
28
<li>Размер файла до 2000 Б</li>
28
<li>Размер файла до 2000 Б</li>
29
<li>Правильность JSON-данных.</li>
29
<li>Правильность JSON-данных.</li>
30
</ul><p>Первые пункты довольно просты, а последнему требуется уделить отдельное внимание. Отсановимся на нем подробнее.</p>
30
</ul><p>Первые пункты довольно просты, а последнему требуется уделить отдельное внимание. Отсановимся на нем подробнее.</p>
31
<h3>Валидация JSON</h3>
31
<h3>Валидация JSON</h3>
32
<p>Первым делом нужно быть проверить, что JSON - это действительно JSON. Выбрал проверку парсингом данных: если тест проходит, значит, все в порядке. Еще один тест проверяет наличие необходимых для i18next ключей. В случае ошибки в логе выводится список недостающих ключей.</p>
32
<p>Первым делом нужно быть проверить, что JSON - это действительно JSON. Выбрал проверку парсингом данных: если тест проходит, значит, все в порядке. Еще один тест проверяет наличие необходимых для i18next ключей. В случае ошибки в логе выводится список недостающих ключей.</p>
33
<h3>Локализация ошибок</h3>
33
<h3>Локализация ошибок</h3>
34
<p>Для локалицзации yup через i18next я использовал setLocale(). Но это позволяет получить переводы только для стандартных случаев, но не для тестов получилось добавить переводы только для каких-то стандартных случаев, но не для тестов.</p>
34
<p>Для локалицзации yup через i18next я использовал setLocale(). Но это позволяет получить переводы только для стандартных случаев, но не для тестов получилось добавить переводы только для каких-то стандартных случаев, но не для тестов.</p>
35
<p>Итоговую схему валидации можно посмотреть в файле<a>schema.js</a>.</p>
35
<p>Итоговую схему валидации можно посмотреть в файле<a>schema.js</a>.</p>
36
<h2>Загрузка новых локалей</h2>
36
<h2>Загрузка новых локалей</h2>
37
<p>После завершения подготовительных работ можно приступить к основной функции проекта - добавлению языков.</p>
37
<p>После завершения подготовительных работ можно приступить к основной функции проекта - добавлению языков.</p>
38
<p>Для загрузки используется метод addResourceBundle() библиотеки i18next. После загрузки я обновляю ресурсы с помощью метода reloadResources().</p>
38
<p>Для загрузки используется метод addResourceBundle() библиотеки i18next. После загрузки я обновляю ресурсы с помощью метода reloadResources().</p>
39
<p>Код этой функции представлен в файле<a>handleAddLanguage.js</a>.</p>
39
<p>Код этой функции представлен в файле<a>handleAddLanguage.js</a>.</p>
40
<h3>Toast</h3>
40
<h3>Toast</h3>
41
<p><a>Toast</a>отвечает за всплывающую ошибку в случае, если не удалось загрузить ту или иную локаль С помощью Bootstrap JavaScript реализовать эту функцию было достаточно просто - тем более, что модельное окно управлялось с помощью Bootstrap.</p>
41
<p><a>Toast</a>отвечает за всплывающую ошибку в случае, если не удалось загрузить ту или иную локаль С помощью Bootstrap JavaScript реализовать эту функцию было достаточно просто - тем более, что модельное окно управлялось с помощью Bootstrap.</p>
42
<h3>Дополнения</h3>
42
<h3>Дополнения</h3>
43
<ul><li><strong>Кнопка "Копировать"</strong>. Поскольку копировать текст из модального окна не очень удобно (особенно на телефоне), добавил кнопку копирования примера в буфер обмена.</li>
43
<ul><li><strong>Кнопка "Копировать"</strong>. Поскольку копировать текст из модального окна не очень удобно (особенно на телефоне), добавил кнопку копирования примера в буфер обмена.</li>
44
<li><strong>Блокировка полей</strong>. После успешной загрузки файла кнопка блокируется на пять секунд чтобы нельзя было загрузить что-то еще. Кнопка "копировать в буфер обмена" блокируется на 5 секунд, чтобы пользователь не могу загрузить что-то еще. По той же схеме кнопка блокируется в случае ошибке валидации и отправки данных.</li>
44
<li><strong>Блокировка полей</strong>. После успешной загрузки файла кнопка блокируется на пять секунд чтобы нельзя было загрузить что-то еще. Кнопка "копировать в буфер обмена" блокируется на 5 секунд, чтобы пользователь не могу загрузить что-то еще. По той же схеме кнопка блокируется в случае ошибке валидации и отправки данных.</li>
45
</ul><h2>Итог</h2>
45
</ul><h2>Итог</h2>
46
<p>Работа над проектом заняла у меня гораздо больше времени, чем я рассчитывал. Конечно, на это сильно повлияло то, что я каждый раз добавлял что-то ещё. Зато я узнал много нового: например, как читать файлы или работать с буфером обмена, а также библиотеками yup и i18next, которые пригодятся в работе над<a>RSS агрегатором</a>.</p>
46
<p>Работа над проектом заняла у меня гораздо больше времени, чем я рассчитывал. Конечно, на это сильно повлияло то, что я каждый раз добавлял что-то ещё. Зато я узнал много нового: например, как читать файлы или работать с буфером обмена, а также библиотеками yup и i18next, которые пригодятся в работе над<a>RSS агрегатором</a>.</p>
47
<p>Проект я обязательно добавлю в резюме, а вы можете его посмотреть, перейдя по<a>ссылке</a>. А веб версию<a>здесь</a>.</p>
47
<p>Проект я обязательно добавлю в резюме, а вы можете его посмотреть, перейдя по<a>ссылке</a>. А веб версию<a>здесь</a>.</p>