מדריך קלאודפלייר בעברית

תיעוד 243

לוקליזציה של אתר עם HTMLRewriter

עודכן לאחרונה ב-21 באפריל 2026

במדריך הזה תבנו מנוע לדוגמה לבינאום וללוקליזציה (שמכונים בדרך כלל 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:

npm create cloudflare@latest -- i18n-example

yarn:

yarn create cloudflare i18n-example

pnpm:

pnpm create cloudflare@latest i18n-example

בהגדרה, בחרו באפשרויות הבאות:

  • עבור What would you like to start with?, בחרו Framework Starter.
  • עבור Which development framework do you want to use?, בחרו React.
  • עבור Do you want to deploy your application?, בחרו No.

פרויקט i18n-example שנוצר זה עתה יכיל שתי תיקיות: public ו-src. הן מכילות קבצים ליישום React:

cd i18n-example
ls
public src package.json

צריך לבצע כמה התאמות בפרויקט שנוצר. קודם רוצים להחליף את התוכן שבתוך תיקיית public בקוד ה-HTML שנוצר כברירת מחדל עבור תבנית HTML5 UP שמופיעה בצילום המסך של ההדגמה: הורידו release ↗︎ (קובץ 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 עם טקסט שונה:

קוד הדגמה שמוצג ב-Chrome DevTools עם הרכיבים שתוארו למעלה

מה שמיוחד בדף הזה הוא הוספה של תכונות data ↗︎ ב-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 אפשר לשאול רכיבים כדי לבצע משימות כמו מציאת תכונת data. עם זאת, כפי שהשם מרמז, אפשר גם לשכתב רכיבים על ידי לקיחת מחרוזת מתורגמת והכנסתה ישירות ל-HTML.

תכונה נוספת של הפרויקט הזה מבוססת על כותרת Accept-Language, שקיימת בבקשות נכנסות. אפשר להגדיר את שפת התרגום לכל בקשה, כך שמשתמשים מכל העולם יראו דף רלוונטי מקומית ומתורגם.

#שימוש ב-API של HTML Rewriter

התחילו בקובץ 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, תכונת data מותאמת אישית שאפשר להשתמש בה כדי למצוא מחרוזת מתורגמת תואמת לממשק המשתמש של האתר. ב-ElementHandler אפשר להגדיר פונקציה element, שתיקרא בזמן שכל רכיב מנותח. בתוך הפונקציה element אפשר לשאול את תכונת ה-data המותאמת אישית באמצעות 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.

כדי לממש את זה:

  1. עדכנו את אובייקט strings, הוסיפו שכבה שנייה של זוגות מפתח-ערך, ואפשרו חיפוש מחרוזות בפורמט strings[country][key].
  2. העבירו אובייקט countryStrings אל ElementHandler, כדי שאפשר יהיה להשתמש בו במהלך תהליך הניתוח.
  3. קחו את כותרת Accept-Language מבקשה נכנסת, נתחו אותה, והעבירו את השפה המנותחת אל ElementHandler.

כדי לנתח את כותרת Accept-Language, התקינו את חבילת ה-npm accept-language-parser ↗︎:

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-09-26"
}
"$schema" = "./node_modules/wrangler/config-schema.json"
name = "i18n-example"
pages_build_output_dir = "./public"
# Set this to today's date
compatibility_date = "2026-09-26"

בשלב הבא צריך להגדיר סקריפט פריסה בקובץ package.json בפרויקט. הוסיפו סקריפט deploy עם הערך wrangler pages deploy:

"scripts": {
  "dev": "wrangler pages dev",
  "deploy": "wrangler pages deploy"
}

באמצעות wrangler, פרסו לרשת של Cloudflare באמצעות הפקודה deploy:

npm run deploy

אתר לדוגמה שעבר לוקליזציה בהצלחה ביפנית, בגרמנית ובאנגלית

#משאבים קשורים

במדריך הזה בניתם ופרסתם כלי i18n באמצעות HTMLRewriter. כדי לעיין בקוד המקור המלא של היישום, פנו למאגר ב-GitHub ↗︎.

אם אתם רוצים להתחיל לבנות פרויקטים משלכם, עיינו ברשימה הקיימת של תבניות Quickstart.