next-intl nextjs 16: تخزين المكونات مؤقتًا مع root-params
أتقن دمج next-intl مع nextjs 16 عبر الاستفادة من next/root-params لتمكين التخزين المؤقت للمكونات بأمان دون الحاجة لعملية prop-drilling للـ locale.

تواجه كثير من فرق الهندسة صعوبة في الموازنة بين كفاءة التصيير على الخادم والتدويل المتين. عند الترقية إلى إصدارات Next.js الحديثة، يكتشف المطورون غالبًا أن حلّ اللغة المرتبط بالطلب يمكن أن يتعارض مع التصيير الثابت ونطاقات Server Components المخزنة مؤقتًا.
يشرح هذا الدليل كيفية إعداد next-intl مع Next.js 16 Cache Components باستخدام next/root-params، بحيث تستطيع Server Components المتداخلة تحديد اللغة النشطة دون تمريرها عبر كل layout وpage وcomponent.
next/root-params: تعرض إصدارات Next.js الحديثة مقاطع route الجذرية مثل[locale]كدوال getter غير متزامنة مثلlocale()، بحيث تستطيع Server Components قراءة اللغة النشطة دون prop-drilling.cacheComponents: يفعّل Next.js Cache Components وتوجيه Reactuse cache.proxy.ts: في Next.js 16، أصبحmiddleware.tsمهملاً وتمت إعادة تسميته إلىproxy.ts.
ومن المفيد أيضًا معرفة الآتي:
requestLocale: في next-intl v4، تستقبلgetRequestConfigالقيمةrequestLocale، والتي ينبغي انتظارها، ويجب أن يتضمن الإعداد المُعادlocale.- بدون prop-drilling: تستطيع Server Components المتداخلة تحديد اللغة مباشرة بدلًا من استقبالها من layouts الأب.
- القيود الحالية: صُمم
next/root-paramsللاستخدام في Server Components. لا تستطيع Client Components استيراده أو استدعاءه مباشرة؛ مرّر اللغة كـ prop، أو استخدم APIs التوجيه من جهة العميل عند الحاجة.
ما هو تخزين next-intl المؤقت في Next.js 16؟
في هذا الإعداد، يعني تخزين next-intl المؤقت استخدام Server Components مترجمة مع توجيه React use cache، مع تحديد اللغة النشطة عبر next/root-params بدلًا من request headers.
تقليديًا، اعتمدت مكتبات التدويل غالبًا على الطلب الوارد لتحديد اللغة النشطة. فقد تقرأ header مثل Accept-Language أو cookies أو بيانات طلب أخرى، ثم تمرر اللغة عبر التطبيق.
ينجح ذلك مع التصيير الديناميكي، لكنه يصبح مشكلة عندما تريد تخزين أجزاء من الواجهة مؤقتًا أو prerender لها. ينبغي أن تتجنب نطاقات Server Component المخزنة مؤقتًا APIs المرتبطة بالطلب وغير المخزنة مؤقتًا مثل headers() وcookies().
تجعل Next.js Cache Components هذا الحدّ أكثر وضوحًا. إذا كان component مخزنًا مؤقتًا، فينبغي أن يعتمد على مدخلات آمنة للتخزين المؤقت. وبالنسبة إلى routes المترجمة، يكون مقطع URL نفسه مفتاح تخزين مؤقت أفضل من request headers.
المشكلة: التخزين المؤقت وتحديد اللغة
قبل next/root-params، كان المطورون الذين يستخدمون next-intl مع التصيير الثابت يعتمدون غالبًا على setRequestLocale(locale) لإتاحة اللغة دون فرض التصيير الديناميكي.
ينجح هذا الأسلوب، لكنه يضيف boilerplate. يجب استدعاء الدالة في كل layout وpage يُفترض أن يتم تصييرها بشكل ثابت، لأن Next.js يمكنه تصيير layouts وpages بشكل مستقل.
يوفر next/root-params مسارًا أنظف. فهو يسمح لـ Server Components بقراءة root route params مثل [locale] مباشرة، دون تمرير اللغة عبر props.
يعرض next/root-params دوال getter غير متزامنة مولّدة للـ root params، مثل locale() أو lang().
| نهج البنية | تحديد اللغة | متوافق مع use cache؟ |
Boilerplate |
|---|---|---|---|
| التصيير المرتبط بالطلب | headers() / cookies() |
غير مناسب داخل النطاقات المخزنة مؤقتًا | منخفض |
| فرض الثبات | setRequestLocale(locale) |
نعم | مرتفع |
| نمط root params | next/root-params |
نعم، لـ Server Components | منخفض |
الإصدارات والقيود الحالية
استخدم هذا النمط فقط عندما تدعم الإصدارات المثبتة لديك APIs التالية:
- Next.js 16 مع
cacheComponents - إصدار Next.js يتضمن
next/root-params - إصدار حديث من next-intl v4
- React 19
مرّ next/root-params بمراحل تجريبية وموثقة خلال خط إصدارات Next.js 16. تحقق من أن إصدار Next.js المثبت لديك يعرض next/root-params قبل استبدال setRequestLocale() في الإنتاج.
يُعد next/root-params الخلف لواجهة API السابقة unstable_rootParams. وهو يسمح بتوليد دوال getter غير متزامنة من root route params مثل locale() أو lang().
القيود الحالية:
- لا تستطيع Client Components استيراد
next/root-paramsأو استدعاءه مباشرة. - Server Actions غير مدعومة.
- Route Handlers غير مدعومة.
- صُمم
next/root-paramsللاستخدام في Server Components. - إذا كنت تحتاج إلى اللغة في Client Component، فمرّرها من Server Component أو اقرأ route params باستخدام APIs التوجيه من جهة العميل مثل
useParams. - اختبر دائمًا إصدارات Next.js وnext-intl الدقيقة لديك قبل شحن هذا النمط في الإنتاج.
تفعيل Cache Components وroot params
فعّل Cache Components وroot params في next.config.ts.
// next.config.ts
import createNextIntlPlugin from 'next-intl/plugin';
import type { NextConfig } from 'next';
const withNextIntl = createNextIntlPlugin();
const nextConfig: NextConfig = {
cacheComponents: true,
experimental: {
rootParams: true,
},
};
export default withNextIntl(nextConfig);
cacheComponents خيار على المستوى الأعلى. في Next.js 16، يتحكم في نموذج برمجة Cache Components ويوحّد إعدادات ppr وuseCache وdynamicIO السابقة.
يمكن تفعيل rootParams صراحةً ضمن experimental، بينما يفعّل cacheComponents نموذج التخزين المؤقت الذي يجعل هذا النمط مفيدًا.
بنية التطبيق المطلوبة
لكي يعرض next/root-params القيمة [locale]، يجب أن يكون مقطع اللغة جزءًا من شجرة root layout. هذا يعني أن root layout لديك ينبغي أن يكون داخل app/[locale]/layout.tsx.
البنية الموصى بها:
src/
├── i18n/
│ ├── routing.ts
│ └── request.ts
├── proxy.ts
└── app/
└── [locale]/
├── layout.tsx
└── page.tsx
في هذا النمط، تجنب وضع root app/layout.tsx فوق [locale]، لأن [locale] يجب أن يكون جزءًا من شجرة root layout لكي يُعرض عبر next/root-params.
ما زالت route parameters الأعمق في الشجرة تُستخدم عبر prop باسم params. على سبيل المثال، في app/[locale]/blog/[slug]/page.tsx، يمكن أن تكون locale root param، بينما يبقى slug route param عاديًا.
إعداد proxy.ts
في Next.js 16، أصبح middleware.ts مهملاً وتمت إعادة تسميته إلى proxy.ts. ينبغي تسمية الدالة المصدّرة proxy، أو يمكنك استخدام صيغة default export المدعومة.
// src/proxy.ts
import createMiddleware from 'next-intl/middleware';
import { routing } from './i18n/routing';
export const proxy = createMiddleware(routing);
export const config = {
matcher: '/((?!api|trpc|_next|_vercel|.*\\..*).*)',
};
يستثني matcher المسارات الداخلية الشائعة، وAPI routes، وVercel internals، والملفات ذات الامتدادات مثل favicon.ico.
ملاحظة حول Runtime
يستخدم proxy.ts بيئة Node.js runtime. خيار الإعداد runtime غير متاح في ملفات Proxy.
إذا كنت تحتاج تحديدًا إلى سلوك Edge runtime، فإن middleware.ts لا يزال يعمل في Next.js 16، لكنه مهمل. ومن المتوقع إزالته في إصدار مستقبلي.
إعداد next-intl request config
في next-intl v4، تستقبل getRequestConfig القيمة requestLocale عند استخدام التوجيه المعتمد على اللغة. ينبغي انتظارها وإرجاع قيمة locale النهائية.
يمكنك أيضًا الرجوع إلى next/root-params عندما تكون requestLocale غير متاحة في نطاقات Server Component المخزنة مؤقتًا.
// src/i18n/request.ts
import { locale as getRootLocale } from 'next/root-params';
import { hasLocale } from 'next-intl';
import { getRequestConfig } from 'next-intl/server';
import { notFound } from 'next/navigation';
import { routing } from './routing';
export default getRequestConfig(async ({ requestLocale }) => {
let locale = await requestLocale;
if (!locale) {
const paramValue = await getRootLocale();
if (hasLocale(routing.locales, paramValue)) {
locale = paramValue;
} else {
notFound();
}
}
return {
locale,
messages: (await import(`../../messages/${locale}.json`)).default,
};
});
يزيل هذا الحاجة إلى استدعاء setRequestLocale(locale) عبر كل layout وpage في حالة الاستخدام هذه التي تركز على التخزين المؤقت.
خارج هذا الإعداد، تظل setRequestLocale() هي طريقة next-intl الموثقة لتفعيل التصيير الثابت.
تبسيط localized root layout
يمكن لـ localized root layout الآن قراءة اللغة النشطة مباشرة من next/root-params.
// src/app/[locale]/layout.tsx
import { locale as getRootLocale } from 'next/root-params';
import { hasLocale } from 'next-intl';
import { notFound } from 'next/navigation';
import type { ReactNode } from 'react';
import { routing } from '@/i18n/routing';
export function generateStaticParams() {
return routing.locales.map((locale) => ({ locale }));
}
type LocaleLayoutProps = {
children: ReactNode;
};
export default async function LocaleLayout({ children }: LocaleLayoutProps) {
const locale = await getRootLocale();
if (!hasLocale(routing.locales, locale)) {
notFound();
}
return (
<html lang={locale}>
<body>{children}</body>
</html>
);
}
لا تزال generateStaticParams() مهمة لعمل prerendering للـ routes المترجمة. مع تفعيل Cache Components، تحتاج root parameters إلى قيم ثابتة من أجل shells قابلة للـ prerender.
استخدام use cache مع components مترجمة
بمجرد إتاحة اللغة عبر next/root-params، يمكن لـ Server Components المخزنة مؤقتًا استخدامها كجزء من مدخلاتها الآمنة للتخزين المؤقت.
// src/app/[locale]/pricing/PricingSection.tsx
import { locale as getRootLocale } from 'next/root-params';
import { getTranslations } from 'next-intl/server';
async function fetchPricingTiers(locale: string) {
return [
{ id: '1', title: locale === 'de' ? 'Basis' : 'Basic' },
{ id: '2', title: locale === 'de' ? 'Profi' : 'Pro' },
];
}
export default async function PricingSection() {
'use cache';
const locale = await getRootLocale();
const t = await getTranslations('PricingSection');
const tiers = await fetchPricingTiers(locale);
return (
<section className="rounded-xl border border-neutral-200 p-6">
<h2 className="text-xl font-bold">{t('heading')}</h2>
<ul className="mt-4 space-y-2">
{tiers.map((tier) => (
<li key={tier.id} className="text-neutral-600">
{tier.title}
</li>
))}
</ul>
</section>
);
}
يتيح هذا للمكونات المتداخلة بعمق جلب الترجمات والبيانات المترجمة دون استقبال locale كـ prop من page أو layout.
يمكن لـ Next.js تتبع دوال getter الخاصة بـ root parameters التي تستخدمها دالة مخزنة مؤقتًا. وهذا يعني أن المخرجات المخزنة مؤقتًا يمكن فصلها حسب root parameter ذي الصلة، مثل locale، بدلًا من الاعتماد على request headers.
التحقق من production build
شغّل production build:
npm run build
ينبغي أن تظهر routes القابلة بالكامل للـ prerendering كـ static أو prerendered في مخرجات البناء.
إذا أصبح route مترجم ديناميكيًا، افحص مسار التصيير بحثًا عن:
headers()cookies()- وصول غير مخزن مؤقتًا إلى البيانات
- APIs مرتبطة بالطلب
generateStaticParams()مفقودة- منطق route يمنع prerendering
لا تستطيع الدوال المخزنة مؤقتًا الوصول مباشرة إلى cookies() أو headers() أو searchParams؛ اقرأها خارج النطاق المخزن مؤقتًا ومررها إليه.
ليس من الضروري أن يكون كل route مترجم ثابتًا. الهدف هو جعل routes الثابتة والمخزنة مؤقتًا ممكنة دون prop-drilling للغة.
أخطاء شائعة
1. إبقاء app/layout.tsx فوق [locale]
إذا لم يكن [locale] جزءًا من شجرة root layout، فلن يستطيع next/root-params عرضه كـ root param.
انقل root layout إلى:
app/[locale]/layout.tsx
2. التعامل مع searchParams كدالة
في صفحات Next.js App Router الحديثة، تُعد searchParams عبارة عن Promise prop. انتظرها مباشرة.
الصحيح:
const params = await searchParams;
الخطأ:
const params = await searchParams();
بالنسبة إلى Client Components، استخدم دالة React use() لقراءة الـ Promise بدلًا من جعل component async.
3. استخدام اصطلاحات middleware القديمة
لا يزال middleware.ts يعمل في Next.js 16، لكنه مهمل.
استخدم:
proxy.ts
وصدّر إما دالة default أو دالة مسماة proxy:
export const proxy = createMiddleware(routing);
4. استخدام إصدارات next-intl قديمة
استخدم إصدارًا حديثًا من next-intl v4. لا يوفر next-intl v3 سلوك request config نفسه المطلوب لهذا النمط.
قبل نشر تثبيت إصدار محدد للحزمة، تحقق من إصدار الحزمة الحالي باستخدام package manager لديك.
5. توقع دعم مباشر لـ Client Component أو Server Action أو Route Handler
next/root-params مخصص لـ Server Components. لا تستطيع Client Components استيراده أو استدعاءه مباشرة، كما أنه لا يدعم حاليًا Server Actions أو Route Handlers.
إذا كنت تحتاج إلى اللغة في Client Component، فمررها من Server Component أو استخدم APIs التوجيه من جهة العميل مثل useParams.
إذا كنت تحتاج إلى اللغة في Server Action، فمررها صراحة كوسيط من component الذي يستدعي action.
الأسئلة الشائعة
كيف أستخدم use cache مع next-intl؟
فعّل cacheComponents: true في next.config.ts.
إذا كان إصدار Next.js لديك يتضمن next/root-params، ففعّل أيضًا root params واضبط getRequestConfig لتحديد اللغة من requestLocale، مع استخدام next/root-params كخيار احتياطي عند الحاجة.
// next.config.ts
const nextConfig = {
cacheComponents: true,
experimental: {
rootParams: true,
},
};
لماذا يمكن أن يتسبب التعامل مع اللغة في كسر التصيير الثابت؟
يمكن أن يكسر التعامل مع اللغة التصيير الثابت عندما يعتمد على APIs مرتبطة بالطلب مثل headers() أو cookies(). تجعل هذه APIs التصيير خاصًا بالطلب، ما يتعارض مع التصيير الثابت ونطاقات Server Component المخزنة مؤقتًا.
ما هو next/root-params؟
next/root-params هو Next.js server API يعرض root route params كدوال getter غير متزامنة.
على سبيل المثال، إذا كان root dynamic segment لديك هو [locale]، يمكنك استخدام:
import { locale } from 'next/root-params';
const value = await locale();
إذا كان segment لديك هو [lang]، فإن دالة getter المولدة هي lang().
يجب أن تكون أسماء root parameters معرّفات JavaScript صالحة، لذلك تجنب أسماء مثل [post-slug] للـ root params التي تريد الوصول إليها بهذه الطريقة.
هل ما زلت أحتاج إلى setRequestLocale؟
بالنسبة إلى نمط next/root-params وCache Components هذا، لا تحتاج عادةً إلى استدعاء setRequestLocale() في كل page وlayout.
خارج هذا الإعداد، أو في إصدارات Next.js التي لا يتوفر فيها next/root-params، تظل setRequestLocale() هي طريقة next-intl الموثقة لتفعيل التصيير الثابت.
هل يمكنني استخدام next/root-params داخل unstable_cache؟
لا. استخدم توجيه React use cache مع Cache Components بدلًا من ذلك.
صُمم next/root-params للعمل مع use cache، حيث يستطيع Next.js تتبع دوال getter الخاصة بـ root parameter التي تستخدمها الدالة المخزنة مؤقتًا.
الخلاصة
تجعل Next.js 16 Cache Components حدود التصيير أكثر وضوحًا، وتحتاج التطبيقات المدوّلة إلى تحديد لغة يعمل داخل تلك الحدود.
من خلال الجمع بين cacheComponents وnext/root-params وإعداد request configuration في next-intl v4، يمكنك إزالة تكرار تمرير locale عبر props، وتجنب تحديد اللغة المعتمد على request headers داخل Server Components المخزنة مؤقتًا، والحفاظ على أهلية routes المترجمة للـ prerendering.
إذا كنت تبني SaaS dashboards متعددة اللغات أو admin panels أو template products، فإن هذا النمط يمنحك أساسًا أنظف لـ Server Components مترجمة في Next.js 16.
ابنِ أسرع مع Aniq UI
تمنحك قوالب Aniq UI أساسات Next.js جاهزة للإنتاج مع TypeScript وTailwind CSS وApp Router layouts وServer Components وanimations وأنماط React الحديثة.
إذا كنت تبني SaaS dashboard أو landing page أو admin panel، فإن البدء من قالب مصقول يمكن أن يوفر وقت الإعداد في routing وlayouts وحالات الواجهة وأنماط التصيير.
المراجع
- وثائق Next.js Proxy
- دليل ترقية Next.js 16
- وثائق Next.js Cache Components
- وثائق Next.js
use cache - وثائق اصطلاح ملف Next.js
page.js - وثائق Next.js
useParams - وثائق إعداد routing في next-intl
- وثائق request configuration في next-intl
- نقاش next-intl حول root params
- وثائق Next.js
next/root-paramsفي مستودع Vercel


