كيفية ترجمة بيانات وصفية للصفحة في TanStack Start v1

ترجمة البيانات الوصفية للبحث ووسائل التواصل الاجتماعي

المشكلة

تظهر البيانات الوصفية للصفحة—العناوين والأوصاف—في علامات تبويب المتصفح، والإشارات المرجعية، ونتائج البحث، ومعاينات وسائل التواصل الاجتماعي. عندما لا تتطابق لغة البيانات الوصفية مع لغة محتوى الصفحة، يواجه المستخدمون تناقضًا صارخًا قبل حتى مشاهدة الصفحة. صفحة إسبانية بعنوان إنجليزي في نتائج البحث تشير إلى جودة توطين ضعيفة. قد تفسر محركات البحث هذا التناقض كإشارة تصنيف، مما قد يقلل من الظهور في نتائج البحث الخاصة باللغة.

هذا الانفصال يقوض تجربة المستخدم في مرحلة الاكتشاف. يتوقع المستخدمون الذين يبحثون بلغتهم المفضلة أن تتطابق البيانات الوصفية، والتناقض يضعف الثقة قبل النقرة الأولى.

الحل

ترجمة البيانات الوصفية للصفحة باستخدام نفس موارد الترجمة المستخدمة لمحتوى الصفحة. حدد دالة head في تكوين المسار الخاص بك تصل إلى السلاسل المترجمة وتعيد البيانات الوصفية للعنوان والوصف المترجمة. هذا يضمن الاتساق بين ما يظهر في واجهة المتصفح، ونتائج البحث، والصفحة المعروضة.

من خلال استخدام تنسيق الرسائل من react-intl داخل دالة head، تبقى البيانات الوصفية متزامنة مع سير عمل الترجمة الخاص بك وتتحدث تلقائيًا عند تغيير اللغة.

الخطوات

1. إنشاء مساعد لتنسيق الرسائل خارج مكونات React

تعمل دالة head خارج شجرة مكونات React حيث تكون الخطافات (hooks) غير متاحة. قم بإنشاء أداة مساعدة تقوم بتنسيق الرسائل باستخدام createIntl من react-intl.

import { createIntl, createIntlCache } from "react-intl";

const cache = createIntlCache();

export function formatMetadataMessage(
  locale: string,
  messages: Record<string, string>,
  id: string,
  values?: Record<string, string | number>,
): string {
  const intl = createIntl({ locale, messages }, cache);
  return intl.formatMessage({ id }, values);
}

يقوم هذا المساعد بإنشاء نسخة intl عند الطلب للاستخدام في سياقات غير React مثل دالة head.

2. تحديد مفاتيح ترجمة البيانات الوصفية

أضف مفاتيح العنوان والوصف إلى ملفات الترجمة الخاصة بك لكل صفحة تحتاج إلى بيانات وصفية مترجمة.

export const enMessages = {
  "page.home.title": "Welcome to Our Site",
  "page.home.description": "Discover amazing content in your language",
  "page.about.title": "About Us",
  "page.about.description": "Learn more about our mission and team",
};

export const esMessages = {
  "page.home.title": "Bienvenido a Nuestro Sitio",
  "page.home.description": "Descubre contenido increíble en tu idioma",
  "page.about.title": "Acerca de Nosotros",
  "page.about.description": "Conoce más sobre nuestra misión y equipo",
};

تتبع هذه المفاتيح نفس نمط ترجمات المكونات الخاصة بك، مما يحافظ على جميع المحتويات المترجمة في مكان واحد.

3. إضافة دالة head إلى المسار الخاص بك

استخدم خيار head في createFileRoute لإرجاع البيانات الوصفية المترجمة. قم بالوصول إلى اللغة الحالية من معلمات المسار أو بيانات المحمّل، ثم قم بتنسيق الرسائل باستخدام المساعد الخاص بك.

import { createFileRoute } from "@tanstack/react-router";
import { formatMetadataMessage } from "../utils/formatMetadataMessage";
import { enMessages, esMessages } from "../i18n/messages";

const messagesByLocale = {
  en: enMessages,
  es: esMessages,
};

export const Route = createFileRoute("/$locale/about")({
  head: ({ params }) => {
    const locale = params.locale || "en";
    const messages = messagesByLocale[locale] || messagesByLocale.en;

    return {
      meta: [
        {
          title: formatMetadataMessage(locale, messages, "page.about.title"),
        },
        {
          name: "description",
          content: formatMetadataMessage(
            locale,
            messages,
            "page.about.description",
          ),
        },
      ],
    };
  },
  component: AboutPage,
});

function AboutPage() {
  return <div>About content</div>;
}

تعمل دالة head أثناء مطابقة المسار وتقوم بإرجاع كائنات البيانات الوصفية التي يقوم TanStack Start بعرضها في رأس المستند.

4. استخدام بيانات المحمّل للبيانات الوصفية الديناميكية

عندما تعتمد البيانات الوصفية على البيانات التي تم جلبها، قم بالوصول إلى loaderData في دالة head لدمج المحتوى الديناميكي مع قوالب الترجمة.

import { createFileRoute } from "@tanstack/react-router";
import { formatMetadataMessage } from "../utils/formatMetadataMessage";
import { enMessages, esMessages } from "../i18n/messages";

const messagesByLocale = {
  en: enMessages,
  es: esMessages,
};

export const Route = createFileRoute("/$locale/posts/$postId")({
  loader: async ({ params }) => {
    const post = await fetchPost(params.postId);
    return { post };
  },
  head: ({ params, loaderData }) => {
    const locale = params.locale || "en";
    const messages = messagesByLocale[locale] || messagesByLocale.en;
    const { post } = loaderData;

    return {
      meta: [
        {
          title: formatMetadataMessage(locale, messages, "page.post.title", {
            title: post.title,
          }),
        },
        {
          name: "description",
          content: post.excerpt,
        },
      ],
    };
  },
  component: PostPage,
});

function PostPage() {
  const { post } = Route.useLoaderData();
  return <article>{post.content}</article>;
}

يقوم المحمّل بجلب البيانات قبل تشغيل دالة head، مما يتيح لك إدراج القيم الديناميكية في قوالب البيانات الوصفية المترجمة.