← Cloudflare Pages / pages / tutorials
Локализация веб-сайта с помощью HTMLRewriter
В этом руководстве вы создадите пример движка интернационализации и локализации (обычно называемого i18n и l10n) для вашего приложения, обслуживать содержимое вашего сайта и автоматически переводить его в зависимости от местоположения посетителей в мире.
В этом руководстве используется HTMLRewriter класс, встроенный в среду выполнения Cloudflare Workers, который позволяет разбирать и переписывать HTML прямо в глобальной сети Cloudflare. Это даёт разработчикам возможность эффективно и прозрачно настраивать свои приложения Workers.
Прежде чем продолжить
Все руководства по фреймворкам предполагают, что у вас уже есть базовое понимание Git ↗. Если вы новичок в Git, обратитесь к этому краткое руководство по Git ↗ о том, как настроить Git на локальном компьютере.
Если вы клонируете по SSH, необходимо сгенерировать ключи SSH ↗ на каждом компьютере, с которого вы отправляете или получаете данные из GitHub.
См. документация GitHub ↗ и Документация Git ↗, где это описано подробнее.
Предварительные требования
Это руководство рассчитано на использование существующего веб-сайта. Чтобы упростить процесс, вы используете бесплатный шаблон HTML5 от HTML5 UP ↗. Взяв этот сайт за основу, вы будете использовать HTMLRewriter функциональность платформы Workers, чтобы наложить слой i18n, автоматически переводя сайт в зависимости от языка пользователя.
Если вы хотите развернуть собственную версию сайта, исходный код можно найти на GitHub ↗. Инструкции по развертыванию этого приложения можно найти в файле README проекта.
Создайте новое приложение
Создайте новое приложение с помощью create-cloudflare, CLI для создания и развертывания новых приложений в Cloudflare.
npm create cloudflare@latest -- i18n-exampleДля настройки выберите следующие параметры:
- Для С чего вы хотите начать?, выберите
Framework Starter. - Для Какой фреймворк для разработки вы хотите использовать?, выберите
React. - Для, Хотите развернуть приложение?, выберите
No.
Только что созданный i18n-example проект будет содержать две папки: public и src они содержат файлы для приложения React:
cd i18n-example
lspublic src package.jsonВнесём несколько изменений в сгенерированный проект. Сначала заменим содержимое внутри public директория со стандартным сгенерированным HTML кодом шаблона HTML5 UP, как показано на демонстрационном скриншоте: загрузите релиз ↗ (ZIP-файл) с кодом этого проекта и скопируйте public папку в свой проект, чтобы начать работу.
Далее создайте каталог functions, содержащий index.js файл, именно здесь будет находиться логика приложения.
mkdir functions
cd functions
touch index.jsКроме того, мы удалим src/ директорию, так как её содержимое не требуется для этого проекта. После обновления статического HTML для этого проекта можно сосредоточиться на скрипте внутри functions папка, по адресу index.js.
Основные сведения о data-i18n-key
HTMLRewriter класс, предоставляемый средой выполнения Workers, позволяет разработчикам разбирать HTML и писать код на JavaScript для запроса и преобразования каждого элемента страницы.
Пример сайта в этом руководстве представляет собой базовый одностраничный HTML-проект, расположенный в public директория. Она включает h1 элемент с текстом Example Site и ряд p элементы с разным текстом:
Особенность этой страницы заключается в добавлении атрибуты данных ↗ в HTML: пользовательские атрибуты, определённые для ряда элементов на этой странице. data-i18n-key на h1 тег на этой странице, а также многие из p тегов означает, что существует соответствующий ключ интернационализации, который следует использовать для поиска перевода этого текста:
<!-- source clipped from i18n-example site -->
<div class="inner">
<h1 data-i18n-key="headline">Example Site</h1>
<p data-i18n-key="subtitle">This is my example site. Depending o...</p>
<p data-i18n-key="disclaimer">Disclaimer: the initial translations...</p>
</div>Использование HTMLRewriter, вы разберете HTML внутри ./public/index.html странице. Когда data-i18n-key атрибут найден, используйте значение атрибута, чтобы получить соответствующий перевод из strings объект. С HTMLRewriter, вы можете запрашивать элементы для таких задач, как поиск атрибута данных. Однако, как следует из названия, вы также можете переписывать элементы, вставляя переведённую строку прямо в HTML.
Ещё одна особенность этого проекта основана на Accept-Language заголовок, который присутствует во входящих запросах. Вы можете задавать язык перевода для каждого запроса, что позволяет пользователям со всего мира видеть локально релевантную и переведённую страницу.
Использование HTML Rewriter API
Начните с functions/index.js файл. В этом руководстве всё приложение будет находиться в этом файле.
В этом файле для начала добавьте код по умолчанию для запуска Pages Function.
export function onRequest(context) {
return new Response("Hello, world!");
}Важная часть кода находится в onRequest функция. Чтобы реализовать переводы на сайте, возьмите HTML-ответ, полученный из env.ASSETS.fetch(request) это позволяет получить статический ресурс из вашего проекта Pages и передать его в новый экземпляр HTMLRewriter. При создании экземпляра HTMLRewriter, вы можете подключить обработчики с помощью on функция. Для этого руководства вы будете использовать [data-i18n-key] селектор (см. документация HTMLRewriter для более продвинутых сценариев использования), чтобы найти все элементы с data-i18n-key атрибут, а значит, их нужно перевести. Любой подходящий элемент будет передан экземпляру вашего ElementHandler класс, который будет содержать логику перевода. С помощью созданного экземпляра HTMLRewriter, transform функция принимает response и может быть возвращено клиенту:
export async function onRequest(context) {
const { request, env } = context;
const response = await env.ASSETS.fetch(request);
return new HTMLRewriter()
.on("[data-i18n-key]", new ElementHandler(countryStrings))
.transform(response);
}Преобразование HTML
Ваш ElementHandler будет получать каждый элемент, обработанный HTMLRewriter экземпляр, и благодаря выразительному API вы можете запрашивать информацию о каждом входящем элементе.
В Как это работает, в документации описывается data-i18n-key, пользовательский атрибут данных, который можно использовать для поиска соответствующей переведённой строки интерфейса сайта. В ElementHandler, вы можете определить element функция, которая вызывается при разборе каждого элемента. Внутри element функции вы можете запросить пользовательский атрибут данных с помощью getAttribute:
class ElementHandler {
element(element) {
const i18nKey = element.getAttribute("data-i18n-key");
}
}С i18nKey определён, его можно использовать для поиска соответствующей переведённой строки. Теперь настройте strings объект с парами ключ-значение, соответствующими data-i18n-key значение. Пока что определите одну примерную строку, headline, с немецким string, "Beispielseite" ("Example Site"), и получить его в element функция:
const strings = {
headline: "Beispielseite",
};
class ElementHandler {
element(element) {
const i18nKey = element.getAttribute("data-i18n-key");
const string = strings[i18nKey];
}
}Возьмите переведённый string и вставьте его в исходный элемент с помощью setInnerContent функция:
const strings = {
headline: "Beispielseite",
};
class ElementHandler {
element(element) {
const i18nKey = element.getAttribute("data-i18n-key");
const string = strings[i18nKey];
if (string) {
element.setInnerContent(string);
}
}
}Чтобы убедиться, что всё выглядит как ожидается, используйте встроенную в Wrangler функцию предпросмотра. Вызовите wrangler pages dev ./public чтобы открыть живое превью проекта. Команда обновляет его после каждого изменения кода.
Эту функциональность перевода можно расширить, чтобы предоставлять переводы для конкретных стран на основе входящего запроса и его Accept-Language заголовок. Взяв этот заголовок, разобрав его и передав распознанный язык в вашу ElementHandler, вы можете получить переведённую строку на родном языке пользователя, если она задана в strings.
Чтобы это реализовать:
- Обновите
stringsобъект, добавляя второй уровень пар ключ-значение и позволяя искать строки в форматеstrings[country][key]. - Передайте
countryStringsобъект в нашElementHandler, чтобы её можно было использовать в процессе разбора. - Скопируйте
Accept-Languageзаголовок из входящего запроса, разберите его и передайте распознанный язык вElementHandler.
Чтобы обработать Accept-Language заголовок, установите accept-language-parser ↗ npm-пакет:
npm i accept-language-parserПосле импорта в код используйте пакет, чтобы определить наиболее подходящий язык клиента на основе Accept-Language заголовок и передайте его в ElementHandler. Итоговый код проекта с примером перевода для Германии и Японии (с использованием Google Translate) выглядит так:
import parser from "accept-language-parser";
// do not set to true in production!
const DEBUG = false;
const strings = {
de: {
title: "Beispielseite",
headline: "Beispielseite",
subtitle:
"Dies ist meine Beispielseite. Abhängig davon, wo auf der Welt Sie diese Site besuchen, wird dieser Text in die entsprechende Sprache übersetzt.",
disclaimer:
"Haftungsausschluss: Die anfänglichen Übersetzungen stammen von Google Translate, daher sind sie möglicherweise nicht perfekt!",
tutorial:
"Das Tutorial für dieses Projekt finden Sie in der Cloudflare Workers-Dokumentation.",
copyright: "Design von HTML5 UP.",
},
ja: {
title: "サンプルサイト",
headline: "サンプルサイト",
subtitle:
"これは私の例のサイトです。 このサイトにアクセスする世界の場所に応じて、このテキストは対応する言語に翻訳されます。",
disclaimer:
"免責事項:最初の翻訳はGoogle翻訳からのものですので、完璧ではないかもしれません!",
tutorial:
"Cloudflare Workersのドキュメントでこのプロジェクトのチュートリアルを見つけてください。",
copyright: "HTML5 UPによる設計。",
},
};
class ElementHandler {
constructor(countryStrings) {
this.countryStrings = countryStrings;
}
element(element) {
const i18nKey = element.getAttribute("data-i18n-key");
if (i18nKey) {
const translation = this.countryStrings[i18nKey];
if (translation) {
element.setInnerContent(translation);
}
}
}
}
export async function onRequest(context) {
const { request, env } = context;
try {
let options = {};
if (DEBUG) {
options = {
cacheControl: {
bypassCache: true,
},
};
}
const languageHeader = request.headers.get("Accept-Language");
const language = parser.pick(["de", "ja"], languageHeader);
const countryStrings = strings[language] || {};
const response = await env.ASSETS.fetch(request);
return new HTMLRewriter()
.on("[data-i18n-key]", new ElementHandler(countryStrings))
.transform(response);
} catch (e) {
if (DEBUG) {
return new Response(e.message || e.toString(), {
status: 404,
});
} else {
return env.ASSETS.fetch(request);
}
}
}Развернуть
Инструмент i18n на основе Cloudflare Pages готов, пришло время развернуть его на вашем домене.
Чтобы развернуть приложение в *.pages.dev поддомен, вам нужно указать каталог со статическими ресурсами для раздачи, настроить pages_build_output_dir в файле Wrangler вашего проекта и укажите значение ./public:
{
"$schema": "./node_modules/wrangler/config-schema.json",
"name": "i18n-example",
"pages_build_output_dir": "./public",
// Set this to today's date
"compatibility_date": "2026-08-28"
}"$schema" = "./node_modules/wrangler/config-schema.json"
name = "i18n-example"
pages_build_output_dir = "./public"
# Set this to today's date
compatibility_date = "2026-08-28"Далее настройте скрипт развёртывания в package.json файл в проекте. Добавьте скрипт деплоя со значением wrangler pages deploy:
"scripts": {
"dev": "wrangler pages dev",
"deploy": "wrangler pages deploy"
}Использование wrangler, разверните в сети Cloudflare с помощью deploy команда:
npm run deploy
Дополнительные материалы
В этом руководстве вы создали и развернули инструмент i18n с помощью HTMLRewriter. Чтобы посмотреть полный исходный код этого приложения, обратитесь к репозиторий на GitHub ↗.
Если вы хотите начать создавать собственные проекты, ознакомьтесь с существующим списком Шаблоны для быстрого старта.