Перекладаємо статичні сторінки та сторінки на основі .mdx файлів в проєкті на Gatsby
Підписуйтеся на Telegram-канал «DOU #tech», щоб не пропустити нові технічні статті.
Мої вітання! Мене звати Роман, і я — фронтенд-розробник компанії Rolique. Часто я маю гарні нагоди імплементувати те, без чого важко уявити сучасні сайти та застосунки. Про що саме йдеться? Інтернаціоналізація та локалізація або, як ми називаємо це в нашому побуті, — багатомовність.
Сьогодні досить велику популярність має підхід створення статичних сайтів за допомогою javascript-фреймворків (react, vue) — JAMstack. Лідерами цього напрямку є Gatsby.js та Next.js.
У цій статті я хотів би зупинитись на імплементації багатомовності для Gatsby проєкту, оскільки вона має свої особливості, які, на перший погляд, можуть бути неочевидними навіть для тих, хто вже познайомився з базовими можливостями Gatsby.
Матеріал, сподіваюсь, буде корисним для тих, хто лише знайомиться з можливостями Gatsby, а також і відкриє щось нове користувачам, хто вже спробував цей інструмент на практиці.
Що будемо перекладати
Як відомо, Gatsby — це чудовий інструмент для створення статичних сайтів, який генерує статичні сторінки в процесі збирання проєкту (build), через що браузер користувача відображає їх з мінімальною затримкою.
У Gatsby доступні три режими генерації сторінок:
- SSG (Static Site Generation) — сторінки сайту генеруються наперед, під час збірки проєкту, і є статичними;
- SSR (Server Side Rendering) — сторінка генерується в момент, коли її запитує користувач;
- DSG (Deffered Site Rendering) — схожий на статичну генерацію, але цей режим дозволяє відкласти генерування деяких статичних сторінок до моменту їх запиту користувачем (наприклад, тих, які є найменш відвідуваними, на які не варто витрачати час під час збірки).
Прочитати більше про режими генерації в Gatsby можна на офіційному сайті.
Незважаючи на те, що цей інструмент стає дедалі універсальнішим, а розмаїття типів проєктів, які можуть бути створені за його допомогою, постійно росте — спектр застосування перекладів залишається сталим.
Так можна виділити наступні типи контенту, які можуть потребувати перекладу:
1. Статичні фрази розташовані безпосередньо в коді сторінок чи компонентах проєкту.
2. .md, .mdx файли, які можуть бути джерелом контенту для сторінок сайту.
3. Контент, отриманий з headless СМS або інших джерел.
У цій статті ми будемо говорити про перший пункт. Другий пункт заслуговує також уваги, але іншим разом. А коли мова йде про третій, то CMS якраз і призначені для того, щоб за їх допомогою створювати контент, в тому числі перекладений на різні мови.
CMS(Content Management System) — система керування контентом. Створення Gatsby проєктів на основі даних, отриманих з систем керування контентом (CMS) є одним з принципів JAM стеку (JAMstack). Для цього потрібно, щоб CMS була headless, — тобто вміла за допомогою API віддавати дані, які б описували контент, призначений для побудови сторінок в Gatsby. Майже усі популярні CMS вже вміють це робити. Ознайомитись з повним списком headless CMS’s, які попали в статистику JAM стеку можна за посиланням.
Готуємо Gatsby проєкт
Створення проєкту на Gatsby не є темою даної статті, тому нам доведеться працювати з вже наперед створеним і частково налаштованим проєктом. Репозиторій з початковим станом коду проєкту доступний за посиланням.
Також ви одразу можете поглянути на результат того, що ми отримаємо та ознайомитись з кодом фінальної версії на гітхабі за посиланням.
Після клонування проєкту і встановлення усіх npm залежностей ви отримаєте простий сайт з трьома сторінками, які мінімально стилізовані за допомогою CSS Modules (підтримується Gatsby за замовчуванням). Також кожна сторінка містить по декілька фраз, для яких необхідно буде додати переклади.
# клонуємо репозиторій проєкту
git clone github.com/NewRoman/gatsby-tutor
# переходимо в директорію проєкту
cd gatsby—tutor
# встановлюємо залежності
npm install
# запускаємо gatsby проєкт
npm run develop
Ось який вигляд матиме файлова структура проєкту:
Якщо в процесі розгортання та запуску проєкту не було помилок, то головна сторінка сайту буде доступна за адресою localhost:8000 і матиме такий вигляд:
Що ж, проєкт готовий до імплементації багатомовності, тому не гаймо часу, починаймо!
Обираємо Gatsby плагін для імплементації локалізації та інтернаціоналізації
Офіційна документація Gatsby подає два плагіни, які можуть бути використані для імплементації перекладів (нас цікавлять саме переклади, тому замість довгого «локалізації та інтернаціоналізації» будем використовувати просте й зрозуміле «переклади»):
Вибір може залежати від вашого попереднього досвіду роботи з подібними бібліотеками чи від вимог до функціоналу, який необхідно імплементувати.
gatsby—plugin—react—i18n — більше підходить для випадків, коли ви вже маєте окремі версії сторінок для кожної мови окремо, робота цього плагіну полягає в тому, щоб, для прикладу, українська версія сторінки /about.uk.js була доступною за адресою /uk/about.
react—i18next — сам собою не є плагіном від Gatsby спільноти, тому, трохи покопирсавшись серед бібліотеки плагінів Gatsby, знаходимо плагін, створений на базі react—i18next— gatsby—plugin—react—i18next. От ці react—i18next та i18next вміють дуже багато всього робити (перекладати, форматувати, робити заміни у фразах тощо), окрім того, їх функціонал можна легко розширяти за допомогою додаткових плагінів.
Оскільки створювати окремі файли сторінок для кожної мови окремо ми не будемо, а будемо перекладати фрази, які вже є у файлах, то вибір плагіну gatsby—plugin—react—i18next буде кращим.
Gatsby має детальну документацію, в якій можна знайти відповіді на більшість запитань. Та, Окрім того, спільнота Gatsby активно працює над тим, щоб розширювати поточну функціональність, створюючи та підтримуючи різноманітні плагіни. Тому перед тим, як створювати свій функціонал спочатку спробуйте знайти рішення в бібліотеці плагінів. Імена усіх Gatsby плагінів починаються з gatsby—plugin—* тому їх легко відрізнити від інших бібліотек.
Готуємо Gatsby проєкт до встановлення gatsby—plugin—react—i18next
Оскільки ми плануємо усі переклади зберігати у вигляді json-файлів всередині проєкту, то нам потрібно підготувати місце для цих файлів. Наш сайт має підтримувати дві мови: англійську та українську. Тому потрібно в кореневій директорії створити директорію locales і в ній окремі директорії для кожної мови з іменами, які є скороченим позначеннями мов en та uk. Створювати json-файли в цих директоріях не потрібно, оскільки ми будемо використовувати автоматичну їх генерацію.
Далі ми маємо оголосити, які мови будуть доступними на сайті і мову по замовчуванню. Який підхід вибрати, залежить від вподобань розробника:
— створити деінде файл languages.js — і в ньому оголосити змінні defaultLanguage=’en’ та масив languages=[‘en’, ‘uk’];
— або в кореневій директорії створити файл languages.js — і в ньому оголосити змінні defaultLanguage=’en’ та languages — масив зі значеннями назв директорій, вкладених в locales (в нашому випадку — це ‘en’ та ‘uk’), який будується динамічно.
Тут я обрав другий варіант, оскільки в цьому випадку для додавання нової мови в масив буде достатньо лише створити ще одну директорію в locales.
Файл languages.js:
Цей скрипт, під час виконання, перевіряє вкладені в locales директорії і створює масив languages з їх назв. Також тут оголошується мова за замовчуванням defaultLanguage.
Встановлюємо та налаштовуємо gatsby—plugin—react—i18next
Після того, як ми підготували проєкт для встановлення плагіну gatsby—plugin—react—i18next, наступним кроком буде, власне, встановлення плагіну та бібліотек, від яких залежить його робота.
# встановлюємо плагін і його залежності
npm install ——save gatsby—plugin—react—i18next i18next react—i18next
Далі переходимо до його конфігурації. Для налаштувань плагінів в Gatsby використовується файл gatsby—config.js, який знаходиться у кореневій директорії проєкту.
Процес додавання плагіну складається з двох етапів.
- Саме встановлення.
- Внесення даних про плагін в gatsby—config.js файл
Функціонал встановленого плагіна запрацює лише після того, як ви повідомите Gatsby про те, що він має використовувати плагін у своїй роботі. Це робиться шляхом додавання назви плагіна в масив plugins файлу gatsby—config.js, — це у випадку, якщо для своєї роботи плагін не потребує додаткових налаштувань, і вам достатньо налаштувань за замовчуванням. Проте, якщо для роботи плагіна обов’язково потрібно вказувати певні налаштування або ви бажаєте сконфігурувати його під свої потреби, то в масив plugins необхідно буде додавати не назву плагіна, а об’єкт, який буде містити поле resolve з назвою плагіна та поле options у вигляді об’єкта, який буде використовуватись для значень налаштувань.
Детальніше про усі значення gatsby—config.js можна дізнатись на сторінці офіційної документації.
Отже, відкриваємо gatsby—config.js — і додаємо налаштування для плагіну gatsby—plugin—react—i18next
Тут в першому рядку імпортуються defaultLanguage та масив languages з файлу languages.js, який ми створили раніше.
На цьому етапі нам вже доступні окремі сторінки для кожної з мов у вигляді uk/about, uk/blog та для англійської версії /about, /blog. Проте, щоб мова фраз відповідала мові сторінки, необхідно внести ще ряд змін.
Замінюємо фрази в файлах проєкту на функцію t() з плагіну gatsby—plugin—react—i18next
Тепер, коли плагін налаштовано, можна починати вносити зміни в компоненти та сторінки сайту.
На цьому етапі необхідно замінити усі фрази, які мають перекладатись, на виклики функції t() плагіну gatsby—plugin—react—i18next. При цьому, аргументами функції t() будуть ключі, які використовуватимуться для збереження перекладених фраз в json-файлах.
Щоб ця функція стала доступною, потрібно з gatsby—plugin—react—i18next імпортувати хук, яких містить функцію t()
Використання функції t() для перекладів — це не єдиний спосіб отримати переклад фрази. Ще одним з найрозповсюдженіших способів є використання компонента <Trans>. Обидва підходи працюють і можуть бути використані, проте я, за можливості, намагаюсь використовувати функцію t(), оскільки вона простіша у використанні та до того ж офіційна документація i18—next радить використовувати <Trans> лише тоді, коли не можливо обійтись функцією t(), наголошуючи, що побудова компонентів <Trans> може займати більше часу, що впливатиме на швидкість збирання сторінок (або рендерингу, якщо говоримо про SSR).
Ось як виглядатиме js файл головної сторінки(index.js) після внесення змін:
Функція t() як перший аргумент приймає назву ключа об’єкта, в якому ця фраза зберігається (в нашому випадку — це json-файл). Існує декілька підходів іменувань цих ключів. Функція t() дозволяє використовувати як семантичні значення ключів — t(‘helloMyWorld’), так і фразу в цілому — t(‘Hello my world’). При використанні цілих фраз, в json-файлі перекладів ключі будуть ідентичні самим фразам. Саме цей варіант я й обрав. «Чому» стане зрозуміло, коли мова дійде до автогенерації перекладів в json файли.
Всюди, де потрібно додати підтримку багатомовності, необхідно провести подібні маніпуляції з фразами. У нашому випадку — це файли pages/index.js, pages/about.js, pages/blog.js та components/navigation.js.
Тепер, коли усі фрази замінені, можна перейти до автогенерації перекладів в json-файли.
Додамо автогенерацію перекладів в json файли за допомогою babel—plugin—i18next—extract
Щоб уникнути ручного створення json-файлів перекладів, можна використати плагін, який зробить це автоматично.
Для цього необхідно встановити цей плагін:
# встановлюємо плагін і його залежності
npm install —save—dev babel—plugin—i18next—extract @babel/cli
Далі для його налаштування в кореневій директорії проєкту створимо файл babel—extract.config.js і одразу додамо в нього опції для роботи плагіну:
Звісно, можна і не змінювати конфігурацію, в такому випадку буде задіяна конфігурація за замовчуванням, проте, для тоншого налаштування все ж деякі опції краще змінити. З повним списком опцій можна ознайомитись на сайті плагіна.
Офіційна документація плагіна просить налаштовувати плагін за допомогою файлу .babelrc, але для Getsby проєктів важливо створити окремий файл babel—extract.config.js і там конфігурувати плагін. Це пов’язано з тим, що Gatsby вже використовує для своєї роботи .babelrc, і створивши ще один, ми ризикуємо перевизначити деякі налаштування для Gatsby і порушити коректність роботи проєкту.
Також, для зручності, створюємо в package.json команду для автогенерації json-файлів перекладів, назвемо її extract:
На цьому етапі автогенерація вже працюватиме, тому ми можемо виконати команду extract:
# виконаємо автогенерацію json файлів перекладів
npm run extract
Все ніби працює, проте погляньмо на результат:
У кожній піддиректорії директорії locales було згенеровано json-файл перекладів — locales/en/common.json та locales/uk/common.json. Якщо відкрити один з цих файлів, то побачимо, що він містить фрази з усіх сторінок та компонентів проєкту. Такий підхід цілком підходить для подальшої роботи (особливо для невеликих проєктів), але краще переклади для кожної сторінки чи компонента зберігати в окремих файлах — послуговуючись термінологією i18next будемо такі файли називати namespaces.
Такий підхід має ряд переваг:
- в менших файлах простіше орієнтуватись і розробникові, і перекладачеві;
- є можливість завантажувати лише ті переклади, які дійсно використовуються на сторінці, а не всі, які існують;
- структура файлів перекладів стає зрозумілішою та простішою.
У нашому випадку можна усі переклади поділити на такі namespaces:
- index — для головної сторінки;
- about — для сторінки about;
- blog — для сторінки зі списком блогів blog;
- common — для спільних фраз для всього сайту(назви пунктів меню навігації тощо).
Отож, далі необхідно для кожного файлу вказати, до якого namespace він належить, щоб плагін babel—plugin—i18next—extract створив на кожен namespace окремий json-файл з фразами, які належать до цього namespace. Це легко зробити за допомогою спеціального коментаря i18next—extract—mark—ns—start плагіна babel—plugin—i18next—extract.
Повний список спецкоментарів можна переглянути на сайті плагіна.
Тепер для кожного файлу з pages додамо такі спецкоментарі з назвою його namespace:
Для компонента components/navigation додамо namespace common:
Потрібно бути уважним, оскільки, якщо для якогось файла, де використовується функція t() не буде визначено namespace, то усі фрази з такого файла опиняться в файлі common.json, оскільки саме namespace common є неймспесом за замовчуванням, а усі фрази, де неймспейс не вказаний стаються частиною такого namespace.
Назва неймспейсу за замовчуванням налаштовується. Місце, де це можна зробити — це файл конфігурації плагіну babel—plugin—i18next—extract — babel—extract.config.js значення поля defaultNS: defaultNS: «common».
Видаляємо попередньо згенерований common.json з обох директорій locales/en та locales/uk і знову запускаємо команду автогенерації.
# виконаємо автогенерацію json файлів перекладів
npm run extract
В результаті отримуємо:
Маємо переклади, збережені по різних файлах, імена яких сходяться з іменами неймспесів, які ми визначили раніше. Вміст файлів для обох директорій en та uk ідентичний, тож наступним кроком буде передавання перекладачам файлів з директорії uk. Для зручності можна користуватись спеціальними сервісами (такими як Locize), які призначені для спрощення взаємодії між розробниками та перекладачами. В нашому випадку немає сенсу залучати додаткові сервіси і можна усі фрази з uk перекласти на українську самостійно.
На цей момент, ми маємо згенеровані json-файли перекладів і перекладені фрази на українську мову. Далі необхідно змусити сайт розуміти, які переклади і коли показувати.
Завантажуємо namespaces на сторінки сайту
Як же зробити так, щоб сторінки та компоненти проєкту отримали доступ до json-файлів з locales/en та locales/uk (namespaces)? Це можливо зробити за допомогою gatsby data layer та GraphQL. Тут не буде детального опису взаємодії gatsby data layer та GraphQL, оскільки це заслуговує окремої статті, проте можна завітати на сторінку документації і детальніше ознайомитись з цими поняттями.
Грубо кажучи, data layer — це місце, де збираються усі дані, які описані в javascript-файлах проєкту за допомогою GraphQL queries. В процесі збірки сторінок Gatsby виявляє усі GraphQL queries, завантажує дані, описані ними, і використовує їх для побудови сторінок.
Насправді взаємодія data layer з GraphQL не можлива без одного важливого моменту. А саме — наявності встановленого gatsby—source— плагіну з Gatsby Plugin бібліотеки. Саме ці плагіни дозволяють Gatsby отримувати дані з різноманітних джерел і роблять їх доступними в data layer. Для кожного джерела даних є свій плагін (джерелами можуть бути сторонні сервіси, CMS, локально розташовані файли тощо), в нашому випадку необхідно локальні файли з locales/en та locales/uk зробити доступними в data layer (і як наслідок на сторінках сайту). Для таких потреб існує плагін gatsby—source—filesystem, який потрібно встановити:
# встановлюємо плагін
npm install gatsby—source—filesystem
Вносимо відповідні налаштування для встановленого плагіну в gatsby—config.js, щоб він розумів, з якими саме локальними файлами потрібно працювати:
Необхідні налаштування знаходяться з 15 по 21 рядок
Далі необхідно з кожного файлу сторінки (директорія pages/), де необхідна багатомовність, експортувати graphql query, в якій вказуємо, які саме namespaces потрібні для цієї сторінки.
Для головної сторінки (namespaces [‘common’, ‘index’] — рядок 32):
graphql—index.png
Для сторінки About (namespaces [‘common’, ‘about] — рядок 26):
graphql—about.png
Для сторінки Blog (namespaces [‘common’, ‘blog] — рядок 31):
graphql—blog.png
На цьому етапі фрази вже відповідають мові сторінки і багатомовність працює. Щоб переконатись в цьому достатньо перейти на сторінку /uk/blog або /uk/about — для україномовної версії сторінок і /blog та /about для англійськомовної версії.
Але вручну змінювати адресу, щоб перемикатись між мовами — незручно. Тому необхідно додати перемикач мов і коректну навігацію між сторінками.
Додаємо навігацію з підтримкою багатомовності та перемикач мов
Перш за все додамо простий перемикач мов, який дозволить легко перемикатись між різними мовами сайту. Для цього внесемо зміни в components/header:
language—switcher.png
На що варто звернути увагу в цьому коді. На використання компонента <Link> з пакета gatsby—plugin—react—i18next. Цей компонент, на відміну від однойменного компоненту від Gatsby, може приймати додаткові значення та будувати посилання на сторінки на основі поточної мови користувача, що дозволяє нам коректно перемикати мову, перебуваючи на будь-якій сторінці.
Перемикач мов додано і нижче зображено, який він має вигляд:
language—switcher—ui.png
Хоч перемикання мов і працює, проте навігація не дуже, оскільки при спробі перейти на іншу сторінку при активній українській мові ми завжди попадаємо на англомовну версію сторінки. Щоб це виправити, необхідно внести зміни в components/navigation:
navigation—languages.png
Все, що тут необхідно було зробити — це замінити компонент <Link> на однойменний компонент, але вже з пакета gatsby—plugin—react—i18next. Він формуватиме посилання на сторінки вже з врахуванням активної мови, як було описано вище.
На цьому етапі наш проєкт вміє змінювати мову та відображати сторінки тою мовою, яку вибрав користувач. Але поки що ми додали переклади лише для статичних фраз, які розташовані безпосередньо в коді сторінок чи компонентах сайту.
Проте, часто для створення статей чи блогів в Gatsby проєктах використовуються файли .md чи .mdx. Тому варто також розглянути один зі способів впровадження багатомовності для сторінок, які створюються на основі таких файлів.
Створюємо mdx файли для багатомовних статей
Якщо ви вирішили створити свій перший сайт зі своїми статтями і не маєте бажання і часу розбиратись з інтеграцією CMS, то вам на допомогу може прийти підхід з використанням .mdx файлів, як джерела контенту для вашої статті. Все, що ви розмістите в .mdx файлі може бути відображено на окремій сторінці сайту так, ніби ви цей контент створили самостійно за допомогою html-розмітки. Детальніше про mdx можна почитати тут.
Для початку створимо директорію blog в кореневій директорії проєкту. Вона буде містити піддиректорії, кожна з яких буде присвячена окремій статті. Припустимо, в нас буде три статті. Тому для кожної з них створимо окремі директорії. Також, одразу додамо зображення для кожної статті та сам файл статті в форматі .mdx. Окрім того, нам потрібно мати переклад статті на дві мови, тому для української версії статті створимо також файл у форматі .mdx з кодом мови в її назві (index.uk.mdx).
Mdx файл для англомовної версії статті (blog/first—post/index.mdx):
mdx—en—file.png
Mdx файл для україномовної версії статті (blog/first—post/index.uk.mdx):
mdx—uk—file.png
Аналогічно створюємо директорії для ще двох статей second—post та third—post і додаємо зображення і mdx файли для англійськомовних та україномовних версій статей (на зображенні вище зображено, як виглядатиме директорія blog/ вже зі створеними трьома піддиректоріями).
Ці файли мають бути доступними для наших компонентів та сторінок проєкту. Оскільки, це локальні файли, то ми маємо йти тим самим шляхом, що і для локальних директорій locales/en та locales/uk, коли ми додавали багатомовність для статичних фраз в попередніх розділах. Для цього необхідно в gatsby—config.js додати ще одну опцію для плагіну gatsby—source—filesystem:
blog—filesystem—plugin.png
Також необхідно встановити ще один плагін gatsby—plugin—mdx, який дає змогу перетворювати mdx файли в дані, які можна отримувати за допомогою graphql:
# встановлюємо плагін
npm install gatsby—plugin—mdx
Додаємо щойно встановлений плагін в gatsby—config.js:
gatsby—plugin—mdx—setup.png
Виводимо увесь список існуючих статей на сторінці
Плагіни gatsby—plugin—mdx та gatsby—source—filesystem дозволяють отримати доступ до даних з mdx файлів директорії blog файлам сторінок проєкту. Для цього необхідно створити відповідну graphql query. Оскільки ми вже маємо підготовлену сторінку для списку статей — pages/blog.js, то саме там необхідно внести зміни в існуючу graphql query.
Зміни в query сторінки pages/blog.js (виділений текст на зображенні):
blog—all—query.png
Graphql query описує структуру даних, які отримує компонент (в нашому випадку це компонент сторінки blog — <Blog>) в props компонента. Тому спочатку деструктуруємо статті з props. Потім виводимо інформацію кожної статті за допомогою методу map. Також для побудови посилань на кожну статтю використаємо компонент <Link> з пакета gatsby—plugin—react—i18next (нам необхідні посилання на статті для різних мов, тому краще одразу використати компонент <Link> з plugin—react—i18next аніж з gatsby).
Зміни в компоненті <Blog> (зміни позначені виділеним текстом):
blog—all—component.png
Робота з даними, отриманими з файлів mdx за допомогою graphql може бути трохи неочевидною, тому для того, щоб краще орієнтуватись в цьому, можна ознайомитись з розділом в документації Gatsby.
Ці зміни в pages/blog дозволяють нам отримати і вивести на сторінці blog усі статті, які збережені в форматі .mdx. Поглянемо, як це виглядає на сторінці:
blog—all.png
Як бачимо, ми отримали в списку статті на всіх мовах, хоча мали б отримати лише англомовні, оскільки активна мова користувача — англійська.
Давайте це виправляти.
Виводимо список статей що відповідає вибраній мові користувача
Gatsby надає можливість будувати сторінки динамічно в процесі збірки (build) проєкту. Також є можливість динамічно додавати нові поля в GraphQL. Це можливо за допомогою gatsby node APIs.
Робота з gatsby—node APIs, передбачає що ви вже маєте вищий за початковий рівень знайомства з Gatsby, тому якщо ви ще не працювали з цим, тоді краще ось тут ознайомитись, що це і для чого.
Іншими словами, ми можемо на основі файлів .mdx будувати сторінки динамічно (під час збірки проєкту) та модифікувати дані, які будуть доступні в компонентах сторінок, що отримані за допомогою graphql query. За все це відповідає файл gatsby—node.js, який необхідно створити в кореневій директорії проєкту.
folder—tree—node.png
Опишемо в цьому файлі функцію onCreateNode, у якій для даних типу Mdx додамо нові поля, які дозволять використовувати на сторінці списку статей pages/blog.js для сортування по мові.
gatsby—node—oncreatenode.png
Тепер для graphql query будуть доступні два додані поля locale та isDefault. Тепер поле locale можна використати для сортування статей за мовою, оскільки це поле буде додано до кожної статті і міститиме значення її мови.
Внесемо зміни в graphql query для файлу pages/blog.js, щоб відфільтрувати статті по їх мові:
Тепер, список статей містить лише ті статті, мова яких відповідає поточній мові, обраній користувачем:
Наступним кроком буде створення окремих сторінок для кожної статті.
Створюємо сторінки для кожної статті
Щоб кожна стаття була доступна двома мовами з окремими адресами, знову скористаємось gatsby node APIs. Додамо в gatsby—node.js файл одразу після onCreateNode функцію createPages.
Вона дасть змогу для кожного файлу .mdx сформувати окрему сторінку і зробити доступними дані з відповідного mdx файлу в коді сторінки.
gastby—node—createpage.png
В рядку 57 з директорії templates імпортується blogTemplate компонент. Це пов’язано з тим, що функції createPage для генерації сторінок необхідно повідомити на основі якого шаблону генерувати сторінку.
Ми створили окремий шаблон для сторінки однієї статті на випадок, якщо шаблон цієї сторінки буде відрізнятись (наразі шаблон буде ідентичним до шаблонів інших сторінок). Щоб функція createPage запрацювала — створимо директорію src/templates і файл blog.js в ній.
template—blog.png
Файл шаблону сторінки однієї статті (scr/templates/blog.js):
template—blog—one.png
Тут ми в graphql query формуємо структуру даних, які нам необхідні на цій сторінці: locales — переклади (namespace) для сторінки (тут лише common namespace для меню навігації) та mdx — структура даних однієї статті з файлу .mdx.
Залишається вивести вміст файлу статті .mdx на сторінку.
Виводимо вміст файлів .mdx на сторінках статей
До цього моменту ми послуговувались лише мета даними .mdx файлів статей, які ми отримували в файлах сторінок. Усі такі метадані містяться в об’єкті frontmatter. Це поле ми описували за допомогою graphql query в таких файлах src/pages/blog.js та src/templates/blog.js:
frontmatter—blogs—page.png
frontmatter—blog—template.png
Поля об’єкту frontmatter легко додавати і видаляти, для цього потрібно лише для кожного .mdx файлу додати або видалити значення у верхній частині файлу між знаками ——— ———.
Файл blog/first—post/index.mdx:
blog—fronmatter.png
Іншими словами, усі змінні, що містяться між потрійними знаками ——— можуть бути отримані на сторінці в об’єкті frontmatter за допомогою graphql query. Але окрім метаданих нам ще потрібно вивести на сторінці контент статі, який знаходиться в файлі .mdx поза межами потрійних знаків ———.
Щоб це реалізувати, необхідно встановити додаткові npm пакети, щоб вміст .mdx файлу коректно відображався на сторінці.
# встановлюємо npm пакети
npm install react—markdown
Потім переходимо до scr/templates/blog.js, імпортуємо з цього пакету ReactMarkdown — і вносимо ще деякі зміни до цього файлу (для того, щоб отримати вміст .mdx файлу необхідно також змінити graphql query для цієї сторінки, а саме — додати поле body):
blog—template—body.png
MDXProvider дозволяє коректно виводити вміст .mdx файлів на сторінках, оскільки .mdx мають свій синтаксис, який відрізняється від стандартної html-розмітки.
Без використання MDXProvider вміст mdx файлу буде розпізнаватись як простий текст, тому він необхідний, щоб коректно перетворювати цей текст в jsx розмітку. Іншими словами — за допомогою MDXProvider розмітка з mdx файлів перетворюється в JSX-розмітку. При цьому в MDXProvider можна передати об’єкт з jsx компонентами — components, які будуть замінювати відповідні теги з розмітки mdx файлів в результуючій jsx-розмітці.
Внісши ці зміни і запустивши проєкт, ми отримаємо змогу також перемикати мови як на сторінці списку статей, так і на сторінці однієї статті. Ви можете переконатися в цьому самостійно, відвідавши сторінку однієї статті.
Сторінка однієї статті:
one—post.png
Висновки
Адаптування сайту для використання в різних країнах може бути неабияким викликом і впровадженням багатомовності — це, без перебільшення, дуже важлива частина не лише цього процесу, а й розробки загалом. Розуміння основних етапів цього процесу допоможе швидше обрати оптимальний підхід.
У цій статті ми розібрали впровадження перекладів в Gatsby проєкті для статичних фраз з javascript-файлів та контенту з .mdx файлів (контент, описаний за допомогою Markdown розмітки).
Також розглянули, як можна полегшити процес формування json-файлів для статичних фраз з js-файлів шляхом автогенерації таких json-файлів і розділенням фраз на частини (namespaces).
Як результат ми отримали повністю перекладені на дві мови (англійську та українську) сторінки Gatsby проєкту та відображення контенту з .mdx файлів (статей), відповідно до вибраної користувачем мови.
Немає коментарів
Додати коментар Підписатись на коментаріВідписатись від коментарів