كيفية تحميل الترجمات من الملفات في Next.js (Pages Router) v16

فصل المحتوى القابل للترجمة عن الكود

المشكلة

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

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

الحل

تخزين جميع النصوص الموجهة للمستخدم في ملفات موارد خارجية، منظمة حسب اللغة، مع ملف JSON واحد لكل لغة. يتم تحديد كل رسالة بمفتاح فريد بدلاً من نصها الحرفي. تشير المكونات إلى هذه المفاتيح بدلاً من النصوص المدرجة مباشرة.

تحميل ملف الترجمة المناسب بناءً على اللغة المستلمة من Next.js وتمرير الرسائل إلى موفر react-intl. يمكن للتطبيق بعد ذلك تبديل اللغات عن طريق تحميل ملف مختلف دون تغيير أي كود للمكونات. هذا يفصل المحتوى عن التنفيذ، مما يسمح للمترجمين بالعمل في ملفات JSON قياسية بينما يشير المطورون إلى مفاتيح رسائل ثابتة.

الخطوات

1. إنشاء ملفات ترجمة منظمة حسب اللغة

ضع رسائل الترجمة في ملفات JSON مفصولة حسب اللغة. يحتوي كل ملف على أزواج مفتاح-قيمة حيث المفاتيح هي معرفات ثابتة والقيم هي النصوص المترجمة لتلك اللغة.

{
"welcome": "Welcome back",
"greeting": "Hello, {name}",
"itemCount": "You have {count, plural, one {# item} other {# items}}"
}

أنشئ ملفاً واحداً لكل لغة مدعومة (على سبيل المثال، messages/en.json، messages/es.json، messages/fr.json) في دليل messages في جذر مشروعك. استخدم نفس المفاتيح في جميع الملفات حتى يتمكن react-intl من البحث عن الترجمة الصحيحة للغة النشطة.

2. تحميل الرسائل في getStaticProps

اقرأ ملف الترجمة بناءً على اللغة المستلمة من Next.js في getStaticProps. يضمن هذا توفر الرسائل من جانب الخادم وتمريرها إلى الصفحة كخصائص.

import { GetStaticProps } from "next";

export const getStaticProps: GetStaticProps = async (context) => {
  const locale = context.locale || "en";
  const messages = (await import(`../messages/${locale}.json`)).default;

  return {
    props: {
      messages,
    },
  };
};

يقوم الاستيراد الديناميكي بتحميل الملف الخاص باللغة الحالية فقط. يوفر Next.js قيمة locale تلقائياً بناءً على عنوان URL أو تفضيلات المستخدم.

3. تمرير الرسائل إلى IntlProvider في _app

قم بتغليف المكون الجذري الخاص بك باستخدام IntlProvider وقم بتكوينه باللغة الحالية للمستخدم والرسائل المترجمة المقابلة. يمكنك الوصول إلى الرسائل من pageProps حتى تتمكن كل صفحة من توفير ترجماتها الخاصة.

import { AppProps } from "next/app";
import { IntlProvider } from "react-intl";
import { useRouter } from "next/router";

export default function App({ Component, pageProps }: AppProps) {
  const { locale, defaultLocale } = useRouter();

  return (
    <IntlProvider
      locale={locale || "en"}
      defaultLocale={defaultLocale || "en"}
      messages={pageProps.messages}
    >
      <Component {...pageProps} />
    </IntlProvider>
  );
}

يجعل المزود الرسائل متاحة لجميع المكونات في الشجرة. تقوم كل صفحة بتحميل ملف الرسائل الخاص بها عبر getStaticProps، ويستقبل _app تلك الرسائل من خلال pageProps.

4. الإشارة إلى الرسائل بالمفتاح في المكونات

استخدم مكون FormattedMessage أو خطاف useIntl من react-intl لعرض النص المترجم. أشر إلى الرسائل بمفتاحها بدلاً من كتابة النصوص بشكل ثابت.

import { FormattedMessage, useIntl } from "react-intl";

export default function HomePage() {
  const intl = useIntl();
  const userName = "Alice";

  return (
    <div>
      <h1>
        <FormattedMessage id="welcome" />
      </h1>
      <p>
        <FormattedMessage id="greeting" values={{ name: userName }} />
      </p>
      <input placeholder={intl.formatMessage({ id: "searchPlaceholder" })} />
    </div>
  );
}

يبحث react-intl عن الرسالة المترجمة وينسقها عند المعرف المحدد. إذا كانت الترجمة مفقودة، فإنه يعود إلى defaultMessage إذا تم توفيره. يتم إدراج المتغيرات الممررة في خاصية values في سلسلة الرسالة.