كيفية إنشاء خرائط مواقع متعددة اللغات في TanStack Start v1
تنظيم خرائط المواقع حسب اللغة للتوسع
المشكلة
تساعد خرائط المواقع محركات البحث على اكتشاف وفهرسة جميع الصفحات على الموقع. يمكن لموقع متعدد اللغات يحتوي على مئات أو آلاف الصفحات لكل لغة أن ينتج بسرعة خرائط مواقع ضخمة. يصبح ملف واحد يسرد كل عنوان URL لكل لغة صعب الإدارة وقد يتجاوز حدود 50,000 عنوان URL أو 50 ميجابايت المحددة في بروتوكول خريطة الموقع. عندما تقوم بتحديث بنية لغة واحدة، يجب عليك إعادة إنشاء الملف بالكامل والتحقق من صحته. خرائط المواقع الضخمة الأحادية صعبة الصيانة وبطيئة المعالجة ولا تتوسع مع إضافة لغات أو محتوى.
الحل
قسّم خريطة موقعك إلى ملفات متعددة واستخدم ملف فهرس خريطة الموقع لإرسال العديد من خرائط المواقع دفعة واحدة. أنشئ فهرس خريطة موقع على المستوى الأعلى في /sitemap.xml يشير إلى خرائط مواقع منفصلة خاصة باللغة مثل /sitemap-en.xml و /sitemap-es.xml. تنسيق XML لملف فهرس خريطة الموقع مشابه لخريطة الموقع العادية ومحدد بواسطة بروتوكول خريطة الموقع. هذا يحافظ على الملفات الفردية قابلة للإدارة، ويتيح لك تحديث كل لغة بشكل مستقل، ويتوسع بشكل جيد عند إضافة لغات أو صفحات جديدة.
الخطوات
1. إنشاء دالة مساعدة لتوليد XML خريطة الموقع
قم ببناء دالة مساعدة تولد XML صالح لخريطة الموقع من مصفوفة إدخالات URL.
export function generateSitemapXML(urls: Array<{ loc: string; lastmod?: string; changefreq?: string; priority?: number }>): string {
const entries = urls.map(url => {
let entry = ` <url>
<loc>${url.loc}</loc>`
if (url.lastmod) entry += `
<lastmod>${url.lastmod}</lastmod>`
if (url.changefreq) entry += `
<changefreq>${url.changefreq}</changefreq>`
if (url.priority !== undefined) entry += `
<priority>${url.priority}</priority>`
entry += `
</url>`
return entry
}).join('
')
return `<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
${entries}
</urlset>`
}
تقبل هذه الدالة مصفوفة من كائنات URL وتُرجع سلسلة XML منسقة بشكل صحيح مع مساحة الاسم والبنية المطلوبة.
2. إنشاء دالة مساعدة لتوليد XML فهرس خريطة الموقع
قم ببناء دالة مساعدة ثانية تُنشئ فهرس خريطة موقع يشير إلى خرائط مواقع فرعية متعددة.
export function generateSitemapIndexXML(sitemaps: Array<{ loc: string; lastmod?: string }>): string {
const entries = sitemaps.map(sitemap => {
let entry = ` <sitemap>
<loc>${sitemap.loc}</loc>`
if (sitemap.lastmod) entry += `
<lastmod>${sitemap.lastmod}</lastmod>`
entry += `
</sitemap>`
return entry
}).join('
')
return `<?xml version="1.0" encoding="UTF-8"?>
<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
${entries}
</sitemapindex>`
}
يستخدم فهرس خريطة الموقع وسم جذر <sitemapindex> ويتضمن إدخال <sitemap> لكل خريطة موقع، مع إدخال فرعي <loc> لكل وسم أصلي.
3. تحديد مسار خادم لفهرس خريطة الموقع الرئيسي
أنشئ مسار خادم في /sitemap.xml يُرجع فهرس خريطة الموقع الذي يسرد جميع خرائط المواقع الخاصة باللغات.
import { createFileRoute } from "@tanstack/react-router";
import { generateSitemapIndexXML } from "~/utils/sitemap";
const SUPPORTED_LOCALES = ["en", "es", "fr", "de"];
const BASE_URL = "https://example.com";
export const Route = createFileRoute("/sitemap")({
server: {
handlers: {
GET: async () => {
const sitemaps = SUPPORTED_LOCALES.map((locale) => ({
loc: `${BASE_URL}/sitemap-${locale}.xml`,
lastmod: new Date().toISOString().split("T")[0],
}));
const xml = generateSitemapIndexXML(sitemaps);
return new Response(xml, {
headers: {
"Content-Type": "application/xml",
"Cache-Control": "public, max-age=3600",
},
});
},
},
},
});
يُنشئ هذا المسار فهرساً يشير إلى خريطة موقع واحدة لكل لغة ويقدمها بتنسيق XML مع رؤوس تخزين مؤقت مناسبة.
4. تحديد مسارات خادم لخرائط المواقع الخاصة باللغات
أنشئ مسار خادم ديناميكي يُنشئ خريطة موقع لكل لغة بناءً على معامل اللغة المحلية.
import { createFileRoute } from "@tanstack/react-router";
import { generateSitemapXML } from "~/utils/sitemap";
const BASE_URL = "https://example.com";
async function getUrlsForLocale(locale: string) {
return [
{ loc: `${BASE_URL}/${locale}`, changefreq: "daily", priority: 1.0 },
{
loc: `${BASE_URL}/${locale}/about`,
changefreq: "monthly",
priority: 0.8,
},
{
loc: `${BASE_URL}/${locale}/contact`,
changefreq: "monthly",
priority: 0.8,
},
];
}
export const Route = createFileRoute("/sitemap-$locale")({
server: {
handlers: {
GET: async ({ params }) => {
const { locale } = params;
const urls = await getUrlsForLocale(locale);
const xml = generateSitemapXML(urls);
return new Response(xml, {
headers: {
"Content-Type": "application/xml",
"Cache-Control": "public, max-age=3600",
},
});
},
},
},
});
تدعم مسارات الخادم معاملات المسار الديناميكية بنفس طريقة TanStack Router، لذا فإن ملفاً مسمى بـ $locale يُنشئ مساراً يقبل معامل لغة محلية ديناميكي. يتم إنشاء كل خريطة موقع خاصة بلغة بشكل مستقل ويمكن تحديثها دون التأثير على اللغات الأخرى.
5. جلب عناوين URL من مصدر البيانات الخاص بك
استبدل دالة getUrlsForLocale النائبة بمنطق يجلب عناوين URL الفعلية من قاعدة البيانات أو نظام إدارة المحتوى أو تعريفات المسارات الخاصة بك.
async function getUrlsForLocale(locale: string) {
const pages = await db.page.findMany({
where: { locale, published: true },
select: { slug: true, updatedAt: true },
});
return pages.map((page) => ({
loc: `${BASE_URL}/${locale}/${page.slug}`,
lastmod: page.updatedAt.toISOString().split("T")[0],
changefreq: "weekly",
priority: 0.7,
}));
}
يستعلم هذا المثال قاعدة بيانات عن الصفحات المنشورة باللغة المحلية المحددة ويربطها بإدخالات خريطة الموقع مع البيانات الوصفية. اضبط منطق الاستعلام والربط ليتطابق مع نموذج البيانات وبنية عناوين URL الخاصة بك.