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

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

المشكلة

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

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

الحل

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

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

الخطوات

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

تعمل دالة head خارج شجرة مكونات React حيث تكون الخطافات غير متاحة. أنشئ أداة مساعدة تنسق الرسائل باستخدام 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، مما يتيح لك إدراج القيم الديناميكية في قوالب البيانات الوصفية المترجمة.