diff --git a/apps/docs/content/ar/docs/01-app/01-getting-started/08-server-and-client-components.mdx b/apps/docs/content/ar/docs/01-app/01-getting-started/05-server-and-client-components.mdx similarity index 100% rename from apps/docs/content/ar/docs/01-app/01-getting-started/08-server-and-client-components.mdx rename to apps/docs/content/ar/docs/01-app/01-getting-started/05-server-and-client-components.mdx diff --git a/apps/docs/content/ar/docs/01-app/01-getting-started/13-partial-prerendering.mdx b/apps/docs/content/ar/docs/01-app/01-getting-started/06-partial-prerendering.mdx similarity index 100% rename from apps/docs/content/ar/docs/01-app/01-getting-started/13-partial-prerendering.mdx rename to apps/docs/content/ar/docs/01-app/01-getting-started/06-partial-prerendering.mdx diff --git a/apps/docs/content/ar/docs/01-app/01-getting-started/09-fetching-data.mdx b/apps/docs/content/ar/docs/01-app/01-getting-started/07-fetching-data.mdx similarity index 100% rename from apps/docs/content/ar/docs/01-app/01-getting-started/09-fetching-data.mdx rename to apps/docs/content/ar/docs/01-app/01-getting-started/07-fetching-data.mdx diff --git a/apps/docs/content/ar/docs/01-app/01-getting-started/11-updating-data.mdx b/apps/docs/content/ar/docs/01-app/01-getting-started/08-updating-data.mdx similarity index 100% rename from apps/docs/content/ar/docs/01-app/01-getting-started/11-updating-data.mdx rename to apps/docs/content/ar/docs/01-app/01-getting-started/08-updating-data.mdx diff --git a/apps/docs/content/ar/docs/01-app/01-getting-started/10-caching-and-revalidating.mdx b/apps/docs/content/ar/docs/01-app/01-getting-started/09-caching-and-revalidating.mdx similarity index 100% rename from apps/docs/content/ar/docs/01-app/01-getting-started/10-caching-and-revalidating.mdx rename to apps/docs/content/ar/docs/01-app/01-getting-started/09-caching-and-revalidating.mdx diff --git a/apps/docs/content/ar/docs/01-app/01-getting-started/12-error-handling.mdx b/apps/docs/content/ar/docs/01-app/01-getting-started/10-error-handling.mdx similarity index 100% rename from apps/docs/content/ar/docs/01-app/01-getting-started/12-error-handling.mdx rename to apps/docs/content/ar/docs/01-app/01-getting-started/10-error-handling.mdx diff --git a/apps/docs/content/ar/docs/01-app/01-getting-started/07-css.mdx b/apps/docs/content/ar/docs/01-app/01-getting-started/11-css.mdx similarity index 100% rename from apps/docs/content/ar/docs/01-app/01-getting-started/07-css.mdx rename to apps/docs/content/ar/docs/01-app/01-getting-started/11-css.mdx diff --git a/apps/docs/content/ar/docs/01-app/01-getting-started/05-images.mdx b/apps/docs/content/ar/docs/01-app/01-getting-started/12-images.mdx similarity index 100% rename from apps/docs/content/ar/docs/01-app/01-getting-started/05-images.mdx rename to apps/docs/content/ar/docs/01-app/01-getting-started/12-images.mdx diff --git a/apps/docs/content/ar/docs/01-app/01-getting-started/06-fonts.mdx b/apps/docs/content/ar/docs/01-app/01-getting-started/13-fonts.mdx similarity index 100% rename from apps/docs/content/ar/docs/01-app/01-getting-started/06-fonts.mdx rename to apps/docs/content/ar/docs/01-app/01-getting-started/13-fonts.mdx diff --git a/apps/docs/content/ar/docs/01-app/01-getting-started/15-deploying.mdx b/apps/docs/content/ar/docs/01-app/01-getting-started/16-deploying.mdx similarity index 100% rename from apps/docs/content/ar/docs/01-app/01-getting-started/15-deploying.mdx rename to apps/docs/content/ar/docs/01-app/01-getting-started/16-deploying.mdx diff --git a/apps/docs/content/ar/docs/01-app/01-getting-started/16-upgrading.mdx b/apps/docs/content/ar/docs/01-app/01-getting-started/17-upgrading.mdx similarity index 100% rename from apps/docs/content/ar/docs/01-app/01-getting-started/16-upgrading.mdx rename to apps/docs/content/ar/docs/01-app/01-getting-started/17-upgrading.mdx diff --git a/apps/docs/content/ar/docs/01-app/04-deep-dive/caching.mdx b/apps/docs/content/ar/docs/01-app/02-guides/caching.mdx similarity index 100% rename from apps/docs/content/ar/docs/01-app/04-deep-dive/caching.mdx rename to apps/docs/content/ar/docs/01-app/02-guides/caching.mdx diff --git a/apps/docs/content/ar/docs/01-app/02-guides/tailwind-css.mdx b/apps/docs/content/ar/docs/01-app/02-guides/tailwind-css.mdx deleted file mode 100644 index d9d8c2b6..00000000 --- a/apps/docs/content/ar/docs/01-app/02-guides/tailwind-css.mdx +++ /dev/null @@ -1,163 +0,0 @@ ---- -source-updated-at: 2025-06-01T01:32:20.000Z -translation-updated-at: 2025-06-02T19:57:47.341Z -title: كيفية تثبيت Tailwind CSS في تطبيق Next.js الخاص بك -nav_title: Tailwind CSS -description: قم بتنسيق تطبيق Next.js الخاص بك باستخدام Tailwind CSS. ---- - -{/* المحتوى في هذا المستند مشترك بين موجه التطبيق وموجه الصفحات. يمكنك استخدام مكون `المحتوى` لإضافة محتوى خاص بموجه الصفحات. أي محتوى مشترك يجب عدم تضمينه في مكون. */} - -[Tailwind CSS](https://tailwindcss.com/) هو إطار عمل CSS يعتمد على الأدوات (utility-first) وهو متوافق بالكامل مع Next.js. سيرشدك هذا الدليل حول كيفية تثبيت Tailwind CSS في تطبيق Next.js الخاص بك. - -## تثبيت Tailwind - -قم بتثبيت حزم Tailwind CSS اللازمة: - -```bash filename="Terminal" -npm install -D tailwindcss @tailwindcss/postcss postcss -``` - -> **معلومة مفيدة**: إذا كنت تستخدم واجهة سطر الأوامر `create-next-app` لإنشاء مشروعك، سيسألك Next.js عما إذا كنت ترغب في تثبيت Tailwind وسيقوم تلقائيًا بتكوين المشروع. - -## تكوين Tailwind - -قم بإنشاء ملف `postcss.config.mjs` في جذر مشروعك وأضف ملحق `@tailwindcss/postcss` إلى تكوين PostCSS الخاص بك: - -```js filename="postcss.config.mjs" highlight={4} -/** @type {import('tailwindcss').Config} */ -export default { - plugins: { - '@tailwindcss/postcss': {}, - }, -} -``` - -بدءًا من [Tailwind v4](https://tailwindcss.com/blog/tailwindcss-v4)، لا يوجد حاجة إلى أي تكوين افتراضيًا. إذا كنت بحاجة إلى تكوين Tailwind، يمكنك اتباع [التوثيق الرسمي](https://tailwindcss.com/blog/tailwindcss-v4#css-first-configuration) لتكوين ملف CSS العام. - -هناك أيضًا [واجهة سطر أوامر للترقية](https://tailwindcss.com/docs/upgrade-guide) و[دليل](https://tailwindcss.com/docs/upgrade-guide) إذا كان لديك مشروع يعمل بـ Tailwind v3. - - - -## استيراد الأنماط - -أضف [توجيهات Tailwind CSS](https://tailwindcss.com/docs/functions-and-directives#directives) التي سيستخدمها Tailwind لحقن الأنماط التي تم إنشاؤها إلى [ملف الأنماط العام](/docs/app/getting-started/css#global-css) في تطبيقك، على سبيل المثال: - -```css filename="app/globals.css" -@import 'tailwindcss'; -``` - -داخل [تخطيط الجذر](/docs/app/api-reference/file-conventions/layout#root-layout) (`app/layout.tsx`)، قم باستيراد ملف الأنماط `globals.css` لتطبيق الأنماط على كل مسار في تطبيقك. - -```tsx filename="app/layout.tsx" switcher -import type { Metadata } from 'next' - -// هذه الأنماط تنطبق على كل مسار في التطبيق -import './globals.css' - -export const metadata: Metadata = { - title: 'Create Next App', - description: 'Generated by create next app', -} - -export default function RootLayout({ - children, -}: { - children: React.ReactNode -}) { - return ( - - {children} - - ) -} -``` - -```jsx filename="app/layout.js" switcher -// هذه الأنماط تنطبق على كل مسار في التطبيق -import './globals.css' - -export const metadata = { - title: 'Create Next App', - description: 'Generated by create next app', -} - -export default function RootLayout({ children }) { - return ( - - {children} - - ) -} -``` - -## استخدام الفئات - -بعد تثبيت Tailwind CSS وإضافة الأنماط العامة، يمكنك استخدام فئات الأدوات الخاصة بـ Tailwind في تطبيقك. - -```tsx filename="app/page.tsx" switcher -export default function Page() { - return

Hello, Next.js!

-} -``` - -```jsx filename="app/page.js" switcher -export default function Page() { - return

Hello, Next.js!

-} -``` - -
- - - -## استيراد الأنماط - -أضف [توجيهات Tailwind CSS](https://tailwindcss.com/docs/functions-and-directives#directives) التي سيستخدمها Tailwind لحقن الأنماط التي تم إنشاؤها إلى [ملف الأنماط العام](/docs/app/getting-started/css#global-css) في تطبيقك، على سبيل المثال: - -```css filename="styles/globals.css" -@import 'tailwindcss'; -``` - -داخل [ملف التطبيق المخصص](/docs/pages/building-your-application/routing/custom-app) (`pages/_app.js`)، قم باستيراد ملف الأنماط `globals.css` لتطبيق الأنماط على كل مسار في تطبيقك. - -```tsx filename="pages/_app.tsx" switcher -// هذه الأنماط تنطبق على كل مسار في التطبيق -import '@/styles/globals.css' -import type { AppProps } from 'next/app' - -export default function App({ Component, pageProps }: AppProps) { - return -} -``` - -```jsx filename="pages/_app.js" switcher -// هذه الأنماط تنطبق على كل مسار في التطبيق -import '@/styles/globals.css' - -export default function App({ Component, pageProps }) { - return -} -``` - -## استخدام الفئات - -بعد تثبيت Tailwind CSS وإضافة الأنماط العامة، يمكنك استخدام فئات الأدوات الخاصة بـ Tailwind في تطبيقك. - -```tsx filename="pages/index.tsx" switcher -export default function Page() { - return

Hello, Next.js!

-} -``` - -```jsx filename="pages/index.js" switcher -export default function Page() { - return

Hello, Next.js!

-} -``` - -
- -## الاستخدام مع Turbopack - -بدءًا من Next.js 13.1، أصبح Tailwind CSS وPostCSS مدعومين مع [Turbopack](https://turbo.build/pack/docs/features/css#tailwind-css). \ No newline at end of file diff --git a/apps/docs/content/ar/docs/01-app/03-api-reference/01-directives/index.mdx b/apps/docs/content/ar/docs/01-app/03-api-reference/01-directives/index.mdx new file mode 100644 index 00000000..08f5670f --- /dev/null +++ b/apps/docs/content/ar/docs/01-app/03-api-reference/01-directives/index.mdx @@ -0,0 +1,8 @@ +--- +source-updated-at: 2025-08-09T22:43:46.028Z +translation-updated-at: 2025-08-09T22:43:46.028Z +title: التوجيهات (Directives) +description: تُستخدم التوجيهات (Directives) لتعديل سلوك تطبيق Next.js الخاص بك. +--- + +التوجيهات المتاحة هي: \ No newline at end of file diff --git a/apps/docs/content/ar/docs/01-app/05-api-reference/01-directives/use-cache.mdx b/apps/docs/content/ar/docs/01-app/03-api-reference/01-directives/use-cache.mdx similarity index 100% rename from apps/docs/content/ar/docs/01-app/05-api-reference/01-directives/use-cache.mdx rename to apps/docs/content/ar/docs/01-app/03-api-reference/01-directives/use-cache.mdx diff --git a/apps/docs/content/ar/docs/01-app/03-api-reference/01-directives/use-client.mdx b/apps/docs/content/ar/docs/01-app/03-api-reference/01-directives/use-client.mdx new file mode 100644 index 00000000..bfc57fc3 --- /dev/null +++ b/apps/docs/content/ar/docs/01-app/03-api-reference/01-directives/use-client.mdx @@ -0,0 +1,125 @@ +--- +source-updated-at: 2025-08-09T22:43:46.028Z +translation-updated-at: 2025-08-09T22:43:46.028Z +title: استخدام use client +description: تعلم كيفية استخدام توجيه use client لعرض مكون على جانب العميل. +--- + +يعلن توجيه `'use client'` عن نقطة دخول للمكونات التي سيتم عرضها على **جانب العميل** ويجب استخدامه عند إنشاء واجهات مستخدم تفاعلية (UI) تتطلب إمكانيات جافا سكريبت من جانب العميل، مثل إدارة الحالة، ومعالجة الأحداث، والوصول إلى واجهات برمجة تطبيقات المتصفح. هذه ميزة من ميزات React. + +> **معلومة مفيدة:** +> +> لا تحتاج إلى إضافة توجيه `'use client'` إلى كل ملف يحتوي على مكونات العميل. تحتاج فقط إلى إضافته إلى الملفات التي تريد عرض مكوناتها مباشرة داخل مكونات الخادم. يحدد توجيه `'use client'` [حدود](https://nextjs.org/docs/app/building-your-application/rendering#network-boundary) الخادم والعميل، وتعمل المكونات المصدرة من مثل هذا الملف كنقاط دخول إلى العميل. + +## الاستخدام + +لتعريف نقطة دخول لمكونات العميل، أضف توجيه `'use client'` **في أعلى الملف**، قبل أي استيرادات: + +```tsx filename="app/components/counter.tsx" highlight={1} switcher +'use client' + +import { useState } from 'react' + +export default function Counter() { + const [count, setCount] = useState(0) + + return ( +
+

Count: {count}

+ +
+ ) +} +``` + +```jsx filename="app/components/counter.js" highlight={1} switcher +'use client' + +import { useState } from 'react' + +export default function Counter() { + const [count, setCount] = useState(0) + + return ( +
+

Count: {count}

+ +
+ ) +} +``` + +عند استخدام توجيه `'use client'`، يجب أن تكون خصائص مكونات العميل [قابلة للتسلسل](https://react.dev/reference/rsc/use-client#serializable-types). هذا يعني أن الخصائص يجب أن تكون بتنسيق يمكن لـ React تسلسله عند إرسال البيانات من الخادم إلى العميل. + +```tsx filename="app/components/counter.tsx" highlight={4} switcher +'use client' + +export default function Counter({ + onClick /* ❌ الدالة غير قابلة للتسلسل */, +}) { + return ( +
+ +
+ ) +} +``` + +```jsx filename="app/components/counter.js" highlight={4} switcher +'use client' + +export default function Counter({ + onClick /* ❌ الدالة غير قابلة للتسلسل */, +}) { + return ( +
+ +
+ ) +} +``` + +## تداخل مكونات العميل داخل مكونات الخادم + +يسمح لك دمج مكونات الخادم والعميل ببناء تطبيقات تكون سريعة الأداء وتفاعلية في نفس الوقت: + +1. **مكونات الخادم**: استخدمها للمحتوى الثابت، جلب البيانات، والعناصر الصديقة لمحركات البحث. +2. **مكونات العميل**: استخدمها للعناصر التفاعلية التي تتطلب حالة، تأثيرات، أو واجهات برمجة تطبيقات المتصفح. +3. **تكوين المكونات**: قم بتداخل مكونات العميل داخل مكونات الخادم حسب الحاجة لفصل واضح بين منطق الخادم والعميل. + +في المثال التالي: + +- `Header` هو مكون خادم يعالج المحتوى الثابت. +- `Counter` هو مكون عميل يمكّن التفاعل داخل الصفحة. + +```tsx filename="app/page.tsx" highlight={2,8} switcher +import Header from './header' +import Counter from './counter' // هذا مكون عميل + +export default function Page() { + return ( +
+
+ +
+ ) +} +``` + +```jsx filename="app/page.js" highlight={2,8} switcher +import Header from './header' +import Counter from './counter' // هذا مكون عميل + +export default function Page() { + return ( +
+
+ +
+ ) +} +``` + +## المراجع + +راجع [وثائق React](https://react.dev/reference/rsc/use-client) لمزيد من المعلومات حول `'use client'`. \ No newline at end of file diff --git a/apps/docs/content/ar/docs/01-app/03-api-reference/01-directives/use-server.mdx b/apps/docs/content/ar/docs/01-app/03-api-reference/01-directives/use-server.mdx new file mode 100644 index 00000000..8cc2f90a --- /dev/null +++ b/apps/docs/content/ar/docs/01-app/03-api-reference/01-directives/use-server.mdx @@ -0,0 +1,163 @@ +--- +source-updated-at: 2025-08-09T22:43:46.028Z +translation-updated-at: 2025-08-09T22:43:46.028Z +title: استخدام use server +description: تعلم كيفية استخدام توجيه use server لتنفيذ التعليمات البرمجية على الخادم. +--- + +يحدد توجيه `use server` وظيفة أو ملفًا ليتم تنفيذه على **جانب الخادم**. يمكن استخدامه في أعلى الملف للإشارة إلى أن جميع الوظائف في الملف تعمل على جانب الخادم، أو مضمنًا في أعلى الوظيفة لوضع علامة على الوظيفة كـ [وظيفة خادم (Server Function)](https://19.react.dev/reference/rsc/server-functions). هذه ميزة من ميزات React. + +## استخدام `use server` في أعلى الملف + +يوضح المثال التالي ملفًا يحتوي على توجيه `use server` في الأعلى. يتم تنفيذ جميع الوظائف في الملف على الخادم. + +```tsx filename="app/actions.ts" highlight={1} switcher +'use server' +import { db } from '@/lib/db' // عميل قاعدة البيانات الخاص بك + +export async function createUser(data: { name: string; email: string }) { + const user = await db.user.create({ data }) + return user +} +``` + +```jsx filename="app/actions.js" highlight={1} switcher +'use server' +import { db } from '@/lib/db' // عميل قاعدة البيانات الخاص بك + +export async function createUser(data) { + const user = await db.user.create({ data }) + return user +} +``` + +### استخدام وظائف الخادم في مكون العميل + +لاستخدام وظائف الخادم في مكونات العميل، تحتاج إلى إنشاء وظائف الخادم الخاصة بك في ملف مخصص باستخدام توجيه `use server` في أعلى الملف. يمكن بعد ذلك استيراد هذه الوظائف إلى مكونات العميل والخادم وتنفيذها. + +بافتراض أن لديك وظيفة خادم `fetchUsers` في `actions.ts`: + +```tsx filename="app/actions.ts" highlight={1} switcher +'use server' +import { db } from '@/lib/db' // عميل قاعدة البيانات الخاص بك + +export async function fetchUsers() { + const users = await db.user.findMany() + return users +} +``` + +```jsx filename="app/actions.js" highlight={1} switcher +'use server' +import { db } from '@/lib/db' // عميل قاعدة البيانات الخاص بك + +export async function fetchUsers() { + const users = await db.user.findMany() + return users +} +``` + +ثم يمكنك استيراد وظيفة الخادم `fetchUsers` إلى مكون العميل وتنفيذها على جانب العميل. + +```tsx filename="app/components/my-button.tsx" highlight={1,2,8} switcher +'use client' +import { fetchUsers } from '../actions' + +export default function MyButton() { + return +} +``` + +```jsx filename="app/components/my-button.js" highlight={1,2,8} switcher +'use client' +import { fetchUsers } from '../actions' + +export default function MyButton() { + return +} +``` + +## استخدام `use server` مضمنًا + +في المثال التالي، يتم استخدام `use server` مضمنًا في أعلى الوظيفة لوضع علامة عليها كـ [وظيفة خادم (Server Function)](https://19.react.dev/reference/rsc/server-functions): + +```tsx filename="app/posts/[id]/page.tsx" switcher highlight={8} +import { EditPost } from './edit-post' +import { revalidatePath } from 'next/cache' + +export default async function PostPage({ params }: { params: { id: string } }) { + const post = await getPost(params.id) + + async function updatePost(formData: FormData) { + 'use server' + await savePost(params.id, formData) + revalidatePath(`/posts/${params.id}`) + } + + return +} +``` + +```jsx filename="app/posts/[id]/page.js" switcher highlight={8} +import { EditPost } from './edit-post' +import { revalidatePath } from 'next/cache' + +export default async function PostPage({ params }) { + const post = await getPost(params.id) + + async function updatePost(formData) { + 'use server' + await savePost(params.id, formData) + revalidatePath(`/posts/${params.id}`) + } + + return +} +``` + +## اعتبارات الأمان + +عند استخدام توجيه `use server`، من المهم التأكد من أن جميع منطق جانب الخادم آمن وأن البيانات الحساسة تظل محمية. + +### المصادقة والتفويض + +قم دائمًا بمصادقة المستخدمين والتحقق من صلاحياتهم قبل تنفيذ العمليات الحساسة على جانب الخادم. + +```tsx filename="app/actions.ts" highlight={1,7,8,9,10} switcher +'use server' + +import { db } from '@/lib/db' // عميل قاعدة البيانات الخاص بك +import { authenticate } from '@/lib/auth' // مكتبة المصادقة الخاصة بك + +export async function createUser( + data: { name: string; email: string }, + token: string +) { + const user = authenticate(token) + if (!user) { + throw new Error('غير مصرح به') + } + const newUser = await db.user.create({ data }) + return newUser +} +``` + +```jsx filename="app/actions.js" highlight={1,7,8,9,10} switcher +'use server' + +import { db } from '@/lib/db' // عميل قاعدة البيانات الخاص بك +import { authenticate } from '@/lib/auth' // مكتبة المصادقة الخاصة بك + +export async function createUser(data, token) { + const user = authenticate(token) + if (!user) { + throw new Error('غير مصرح به') + } + const newUser = await db.user.create({ data }) + return newUser +} +``` + +## مرجع + +راجع [وثائق React](https://react.dev/reference/rsc/use-server) لمزيد من المعلومات حول `use server`. \ No newline at end of file diff --git a/apps/docs/content/ar/docs/01-app/05-api-reference/02-components/font.mdx b/apps/docs/content/ar/docs/01-app/03-api-reference/02-components/font.mdx similarity index 100% rename from apps/docs/content/ar/docs/01-app/05-api-reference/02-components/font.mdx rename to apps/docs/content/ar/docs/01-app/03-api-reference/02-components/font.mdx diff --git a/apps/docs/content/ar/docs/01-app/05-api-reference/02-components/form.mdx b/apps/docs/content/ar/docs/01-app/03-api-reference/02-components/form.mdx similarity index 100% rename from apps/docs/content/ar/docs/01-app/05-api-reference/02-components/form.mdx rename to apps/docs/content/ar/docs/01-app/03-api-reference/02-components/form.mdx diff --git a/apps/docs/content/ar/docs/01-app/05-api-reference/02-components/image.mdx b/apps/docs/content/ar/docs/01-app/03-api-reference/02-components/image.mdx similarity index 100% rename from apps/docs/content/ar/docs/01-app/05-api-reference/02-components/image.mdx rename to apps/docs/content/ar/docs/01-app/03-api-reference/02-components/image.mdx diff --git a/apps/docs/content/ar/docs/01-app/03-api-reference/02-components/index.mdx b/apps/docs/content/ar/docs/01-app/03-api-reference/02-components/index.mdx new file mode 100644 index 00000000..159edb11 --- /dev/null +++ b/apps/docs/content/ar/docs/01-app/03-api-reference/02-components/index.mdx @@ -0,0 +1,8 @@ +--- +source-updated-at: 2025-08-09T22:43:46.028Z +translation-updated-at: 2025-08-09T22:43:46.028Z +title: المكونات +description: مرجع API لمكونات Next.js المضمنة. +--- + +{/* يتم مشاركة محتوى هذا المستند بين جهاز التوجيه للتطبيق والصفحات. يمكنك استخدام مكون `المحتوى` لإضافة محتوى خاص بجهاز توجيه الصفحات. أي محتوى مشترك يجب عدم تضمينه في مكون. */} \ No newline at end of file diff --git a/apps/docs/content/ar/docs/01-app/05-api-reference/02-components/link.mdx b/apps/docs/content/ar/docs/01-app/03-api-reference/02-components/link.mdx similarity index 100% rename from apps/docs/content/ar/docs/01-app/05-api-reference/02-components/link.mdx rename to apps/docs/content/ar/docs/01-app/03-api-reference/02-components/link.mdx diff --git a/apps/docs/content/ar/docs/01-app/05-api-reference/02-components/script.mdx b/apps/docs/content/ar/docs/01-app/03-api-reference/02-components/script.mdx similarity index 100% rename from apps/docs/content/ar/docs/01-app/05-api-reference/02-components/script.mdx rename to apps/docs/content/ar/docs/01-app/03-api-reference/02-components/script.mdx diff --git a/apps/docs/content/ar/docs/01-app/05-api-reference/03-file-conventions/01-metadata/app-icons.mdx b/apps/docs/content/ar/docs/01-app/03-api-reference/03-file-conventions/01-metadata/app-icons.mdx similarity index 100% rename from apps/docs/content/ar/docs/01-app/05-api-reference/03-file-conventions/01-metadata/app-icons.mdx rename to apps/docs/content/ar/docs/01-app/03-api-reference/03-file-conventions/01-metadata/app-icons.mdx diff --git a/apps/docs/content/ar/docs/01-app/05-api-reference/03-file-conventions/01-metadata/index.mdx b/apps/docs/content/ar/docs/01-app/03-api-reference/03-file-conventions/01-metadata/index.mdx similarity index 100% rename from apps/docs/content/ar/docs/01-app/05-api-reference/03-file-conventions/01-metadata/index.mdx rename to apps/docs/content/ar/docs/01-app/03-api-reference/03-file-conventions/01-metadata/index.mdx diff --git a/apps/docs/content/ar/docs/01-app/05-api-reference/03-file-conventions/01-metadata/manifest.mdx b/apps/docs/content/ar/docs/01-app/03-api-reference/03-file-conventions/01-metadata/manifest.mdx similarity index 100% rename from apps/docs/content/ar/docs/01-app/05-api-reference/03-file-conventions/01-metadata/manifest.mdx rename to apps/docs/content/ar/docs/01-app/03-api-reference/03-file-conventions/01-metadata/manifest.mdx diff --git a/apps/docs/content/ar/docs/01-app/05-api-reference/03-file-conventions/01-metadata/opengraph-image.mdx b/apps/docs/content/ar/docs/01-app/03-api-reference/03-file-conventions/01-metadata/opengraph-image.mdx similarity index 100% rename from apps/docs/content/ar/docs/01-app/05-api-reference/03-file-conventions/01-metadata/opengraph-image.mdx rename to apps/docs/content/ar/docs/01-app/03-api-reference/03-file-conventions/01-metadata/opengraph-image.mdx diff --git a/apps/docs/content/ar/docs/01-app/05-api-reference/03-file-conventions/01-metadata/robots.mdx b/apps/docs/content/ar/docs/01-app/03-api-reference/03-file-conventions/01-metadata/robots.mdx similarity index 100% rename from apps/docs/content/ar/docs/01-app/05-api-reference/03-file-conventions/01-metadata/robots.mdx rename to apps/docs/content/ar/docs/01-app/03-api-reference/03-file-conventions/01-metadata/robots.mdx diff --git a/apps/docs/content/ar/docs/01-app/05-api-reference/03-file-conventions/01-metadata/sitemap.mdx b/apps/docs/content/ar/docs/01-app/03-api-reference/03-file-conventions/01-metadata/sitemap.mdx similarity index 100% rename from apps/docs/content/ar/docs/01-app/05-api-reference/03-file-conventions/01-metadata/sitemap.mdx rename to apps/docs/content/ar/docs/01-app/03-api-reference/03-file-conventions/01-metadata/sitemap.mdx diff --git a/apps/docs/content/ar/docs/01-app/03-api-reference/03-file-conventions/default.mdx b/apps/docs/content/ar/docs/01-app/03-api-reference/03-file-conventions/default.mdx new file mode 100644 index 00000000..5fca6a53 --- /dev/null +++ b/apps/docs/content/ar/docs/01-app/03-api-reference/03-file-conventions/default.mdx @@ -0,0 +1,60 @@ +--- +source-updated-at: 2025-08-09T22:43:46.028Z +translation-updated-at: 2025-08-09T22:43:46.028Z +title: default.js +description: مرجع API لملف default.js. +related: + title: تعلم المزيد عن المسارات المتوازية (Parallel Routes) + links: + - app/api-reference/file-conventions/parallel-routes +--- + +يُستخدم ملف `default.js` لعرض بديل احتياطي داخل [المسارات المتوازية (Parallel Routes)](/docs/app/api-reference/file-conventions/parallel-routes) عندما لا يتمكن Next.js من استعادة الحالة النشطة [للفتحة (slot)](/docs/app/api-reference/file-conventions/parallel-routes#slots) بعد تحميل الصفحة بالكامل. + +أثناء [التنقل الناعم (soft navigation)](/docs/app/getting-started/linking-and-navigating#client-side-transitions)، يحتفظ Next.js بتتبع الحالة _النشطة_ (الصفحة الفرعية) لكل فتحة. ومع ذلك، بالنسبة للتنقلات الصلبة (تحميل الصفحة بالكامل)، لا يمكن لـ Next.js استعادة الحالة النشطة. في هذه الحالة، يمكن عرض ملف `default.js` للصفحات الفرعية التي لا تتطابق مع عنوان URL الحالي. + +خذ بعين الاعتبار هيكل المجلدات التالي. تحتوي فتحة `@team` على صفحة `settings`، بينما لا تحتوي فتحة `@analytics` على ذلك. + +المسارات المتوازية - مسارات غير متطابقة + +عند التنقل إلى `/settings`، ستعرض فتحة `@team` صفحة `settings` مع الحفاظ على الصفحة النشطة الحالية لفتحة `@analytics`. + +عند التحديث، سيعرض Next.js ملف `default.js` لـ `@analytics`. إذا لم يكن `default.js` موجودًا، فسيتم عرض خطأ `404` بدلاً من ذلك. + +بالإضافة إلى ذلك، نظرًا لأن `children` هي فتحة ضمنية، فأنت بحاجة أيضًا إلى إنشاء ملف `default.js` لعرض بديل احتياطي لـ `children` عندما لا يتمكن Next.js من استعادة الحالة النشطة للصفحة الأصلية. + +## المرجع + +### `params` (اختياري) + +وعد (promise) يحل إلى كائن يحتوي على [معلمات المسار الديناميكي (dynamic route parameters)](/docs/app/api-reference/file-conventions/dynamic-routes) من الجزء الجذري وصولاً إلى الصفحات الفرعية للفتحة. على سبيل المثال: + +```tsx filename="app/[artist]/@sidebar/default.js" switcher +export default async function Default({ + params, +}: { + params: Promise<{ artist: string }> +}) { + const { artist } = await params +} +``` + +```jsx filename="app/[artist]/@sidebar/default.js" switcher +export default async function Default({ params }) { + const { artist } = await params +} +``` + +| المثال | عنوان URL | `params` | +| ------------------------------------------ | ------------ | -------------------------------------------- | +| `app/[artist]/@sidebar/default.js` | `/zack` | `Promise<{ artist: 'zack' }>` | +| `app/[artist]/[album]/@sidebar/default.js` | `/zack/next` | `Promise<{ artist: 'zack', album: 'next' }>` | + +- نظرًا لأن الخاصية `params` هي وعد (promise)، يجب عليك استخدام `async/await` أو دالة [`use`](https://react.dev/reference/react/use) في React للوصول إلى القيم. + - في الإصدار 14 وما قبله، كانت `params` خاصية متزامنة (synchronous). للمساعدة في التوافق مع الإصدارات السابقة، لا يزال بإمكانك الوصول إليها بشكل متزامن في Next.js 15، ولكن هذا السلوك سيتم إهماله في المستقبل. \ No newline at end of file diff --git a/apps/docs/content/ar/docs/01-app/05-api-reference/03-file-conventions/dynamic-routes.mdx b/apps/docs/content/ar/docs/01-app/03-api-reference/03-file-conventions/dynamic-routes.mdx similarity index 100% rename from apps/docs/content/ar/docs/01-app/05-api-reference/03-file-conventions/dynamic-routes.mdx rename to apps/docs/content/ar/docs/01-app/03-api-reference/03-file-conventions/dynamic-routes.mdx diff --git a/apps/docs/content/ar/docs/01-app/05-api-reference/03-file-conventions/error.mdx b/apps/docs/content/ar/docs/01-app/03-api-reference/03-file-conventions/error.mdx similarity index 100% rename from apps/docs/content/ar/docs/01-app/05-api-reference/03-file-conventions/error.mdx rename to apps/docs/content/ar/docs/01-app/03-api-reference/03-file-conventions/error.mdx diff --git a/apps/docs/content/ar/docs/01-app/03-api-reference/03-file-conventions/forbidden.mdx b/apps/docs/content/ar/docs/01-app/03-api-reference/03-file-conventions/forbidden.mdx new file mode 100644 index 00000000..4ea12638 --- /dev/null +++ b/apps/docs/content/ar/docs/01-app/03-api-reference/03-file-conventions/forbidden.mdx @@ -0,0 +1,52 @@ +--- +source-updated-at: 2025-08-09T22:43:46.028Z +translation-updated-at: 2025-08-09T22:43:46.028Z +title: forbidden.js +description: مرجع API لملف forbidden.js الخاص. +related: + links: + - app/api-reference/functions/forbidden +version: experimental +--- + +يستخدم ملف **forbidden** لعرض واجهة المستخدم عند استدعاء [دالة `forbidden`](/docs/app/api-reference/functions/forbidden) أثناء المصادقة. بالإضافة إلى السماح لك بتخصيص الواجهة، سيقوم Next.js بإرجاع رمز حالة `403`. + +```tsx filename="app/forbidden.tsx" switcher +import Link from 'next/link' + +export default function Forbidden() { + return ( +
+

Forbidden

+

You are not authorized to access this resource.

+ Return Home +
+ ) +} +``` + +```jsx filename="app/forbidden.jsx" switcher +import Link from 'next/link' + +export default function Forbidden() { + return ( +
+

Forbidden

+

You are not authorized to access this resource.

+ Return Home +
+ ) +} +``` + +## المرجع + +### الخصائص (Props) + +لا تقبل مكونات `forbidden.js` أي خصائص. + +## سجل الإصدارات + +| الإصدار | التغييرات | +| --------- | ------------------------- | +| `v15.1.0` | تم تقديم `forbidden.js`. | \ No newline at end of file diff --git a/apps/docs/content/ar/docs/01-app/03-api-reference/03-file-conventions/index.mdx b/apps/docs/content/ar/docs/01-app/03-api-reference/03-file-conventions/index.mdx new file mode 100644 index 00000000..fcefba8d --- /dev/null +++ b/apps/docs/content/ar/docs/01-app/03-api-reference/03-file-conventions/index.mdx @@ -0,0 +1,6 @@ +--- +source-updated-at: 2025-08-09T22:43:46.028Z +translation-updated-at: 2025-08-09T22:43:46.028Z +title: اصطلاحات نظام الملفات +description: مرجع API لاصطلاحات نظام الملفات في Next.js. +--- \ No newline at end of file diff --git a/apps/docs/content/ar/docs/01-app/03-api-reference/03-file-conventions/instrumentation.mdx b/apps/docs/content/ar/docs/01-app/03-api-reference/03-file-conventions/instrumentation.mdx new file mode 100644 index 00000000..84f94ca3 --- /dev/null +++ b/apps/docs/content/ar/docs/01-app/03-api-reference/03-file-conventions/instrumentation.mdx @@ -0,0 +1,141 @@ +--- +source-updated-at: 2025-08-09T22:43:46.028Z +translation-updated-at: 2025-08-09T22:43:46.028Z +title: ملف instrumentation.js +description: مرجع API لملف instrumentation.js. +related: + title: تعرف على المزيد حول الأداة (Instrumentation) + links: + - app/guides/instrumentation +--- + +يُستخدم ملف `instrumentation.js|ts` لدمج أدوات المراقبة (observability) في تطبيقك، مما يسمح لك بتتبع الأداء والسلوك، وتصحيح الأخطاء في بيئة الإنتاج. + +لاستخدامه، ضع الملف في **الجذر** لتطبيقك أو داخل مجلد [`src`](/docs/app/api-reference/file-conventions/src-folder) إذا كنت تستخدم واحدًا. + +## التصديرات + +### `register` (اختياري) + +يصدّر الملف دالة `register` يتم استدعاؤها **مرة واحدة** عند بدء تشغيل مثيل جديد لخادم Next.js. يمكن أن تكون دالة `register` غير متزامنة (async). + +```ts filename="instrumentation.ts" switcher +import { registerOTel } from '@vercel/otel' + +export function register() { + registerOTel('next-app') +} +``` + +```js filename="instrumentation.js" switcher +import { registerOTel } from '@vercel/otel' + +export function register() { + registerOTel('next-app') +} +``` + +### `onRequestError` (اختياري) + +يمكنك تصدير دالة `onRequestError` بشكل اختياري لتتبع أخطاء **الخادم** لأي مزود مراقبة مخصص. + +- إذا كنت تقوم بتشغيل أي مهام غير متزامنة في `onRequestError`، تأكد من انتظارها (await). سيتم تشغيل `onRequestError` عندما يلتقط خادم Next.js الخطأ. +- قد لا يكون مثيل `error` هو مثيل الخطأ الأصلي الذي تم طرحه، حيث قد يتم معالجته بواسطة React إذا حدث أثناء عرض مكونات الخادم (Server Components). إذا حدث هذا، يمكنك استخدام خاصية `digest` على الخطأ لتحديد نوع الخطأ الفعلي. + +```ts filename="instrumentation.ts" switcher +import { type Instrumentation } from 'next' + +export const onRequestError: Instrumentation.onRequestError = async ( + err, + request, + context +) => { + await fetch('https://.../report-error', { + method: 'POST', + body: JSON.stringify({ + message: err.message, + request, + context, + }), + headers: { + 'Content-Type': 'application/json', + }, + }) +} +``` + +```js filename="instrumentation.js" switcher +export async function onRequestError(err, request, context) { + await fetch('https://.../report-error', { + method: 'POST', + body: JSON.stringify({ + message: err.message, + request, + context, + }), + headers: { + 'Content-Type': 'application/json', + }, + }) +} +``` + +#### المعاملات (Parameters) + +تقبل الدالة ثلاثة معاملات: `error`، `request`، و `context`. + +```ts filename="Types" +export function onRequestError( + error: { digest: string } & Error, + request: { + path: string // مسار المورد، مثل /blog?name=foo + method: string // طريقة الطلب، مثل GET, POST، إلخ + headers: { [key: string]: string } + }, + context: { + routerKind: 'Pages Router' | 'App Router' // نوع الموجه + routePath: string // مسار ملف المسار، مثل /app/blog/[dynamic] + routeType: 'render' | 'route' | 'action' | 'middleware' // السياق الذي حدث فيه الخطأ + renderSource: + | 'react-server-components' + | 'react-server-components-payload' + | 'server-rendering' + revalidateReason: 'on-demand' | 'stale' | undefined // undefined يعني طلبًا عاديًا بدون إعادة التحقق + renderType: 'dynamic' | 'dynamic-resume' // 'dynamic-resume' لـ PPR + } +): void | Promise +``` + +- `error`: الخطأ الذي تم التقاطه (النوع دائمًا `Error`)، وخاصية `digest` وهي المعرف الفريد للخطأ. +- `request`: معلومات الطلب المقروءة فقط المرتبطة بالخطأ. +- `context`: السياق الذي حدث فيه الخطأ. يمكن أن يكون نوع الموجه (App أو Pages Router)، و/أو (مكونات الخادم (`'render'`)، معالجات المسار (`'route'`)، إجراءات الخادم (`'action'`)، أو Middleware (`'middleware'`)). + +### تحديد بيئة التشغيل (Runtime) + +يعمل ملف `instrumentation.js` في كل من بيئة تشغيل Node.js و Edge، ولكن يمكنك استخدام `process.env.NEXT_RUNTIME` لاستهداف بيئة تشغيل محددة. + +```js filename="instrumentation.js" +export function register() { + if (process.env.NEXT_RUNTIME === 'edge') { + return require('./register.edge') + } else { + return require('./register.node') + } +} + +export function onRequestError() { + if (process.env.NEXT_RUNTIME === 'edge') { + return require('./on-request-error.edge') + } else { + return require('./on-request-error.node') + } +} +``` + +## سجل الإصدارات + +| الإصدار | التغييرات | +| --------- | ------------------------------------------------------- | +| `v15.0.0` | إدخال `onRequestError`، تثبيت `instrumentation` | +| `v14.0.4` | دعم Turbopack لـ `instrumentation` | +| `v13.2.0` | إدخال `instrumentation` كخاصية تجريبية | \ No newline at end of file diff --git a/apps/docs/content/ar/docs/01-app/05-api-reference/03-file-conventions/intercepting-routes.mdx b/apps/docs/content/ar/docs/01-app/03-api-reference/03-file-conventions/intercepting-routes.mdx similarity index 100% rename from apps/docs/content/ar/docs/01-app/05-api-reference/03-file-conventions/intercepting-routes.mdx rename to apps/docs/content/ar/docs/01-app/03-api-reference/03-file-conventions/intercepting-routes.mdx diff --git a/apps/docs/content/ar/docs/01-app/05-api-reference/03-file-conventions/layout.mdx b/apps/docs/content/ar/docs/01-app/03-api-reference/03-file-conventions/layout.mdx similarity index 100% rename from apps/docs/content/ar/docs/01-app/05-api-reference/03-file-conventions/layout.mdx rename to apps/docs/content/ar/docs/01-app/03-api-reference/03-file-conventions/layout.mdx diff --git a/apps/docs/content/ar/docs/01-app/03-api-reference/03-file-conventions/loading.mdx b/apps/docs/content/ar/docs/01-app/03-api-reference/03-file-conventions/loading.mdx new file mode 100644 index 00000000..86dc6cda --- /dev/null +++ b/apps/docs/content/ar/docs/01-app/03-api-reference/03-file-conventions/loading.mdx @@ -0,0 +1,169 @@ +--- +source-updated-at: 2025-08-09T22:43:46.028Z +translation-updated-at: 2025-08-09T22:43:46.028Z +title: ملف loading.js +description: مرجع API لملف loading.js. +--- + +يساعدك الملف الخاص `loading.js` في إنشاء واجهة تحميل ذات معنى باستخدام [React Suspense](https://react.dev/reference/react/Suspense). باستخدام هذه الاتفاقية، يمكنك عرض [حالة تحميل فورية](#instant-loading-states) من الخادم أثناء بث محتوى جزء المسار. يتم تبديل المحتوى الجديد تلقائيًا بمجرد اكتماله. + +واجهة التحميل + +```tsx filename="app/feed/loading.tsx" switcher +export default function Loading() { + // أو مكون هيكل تحميل مخصص + return

جاري التحميل...

+} +``` + +```jsx filename="app/feed/loading.js" switcher +export default function Loading() { + // أو مكون هيكل تحميل مخصص + return

جاري التحميل...

+} +``` + +داخل ملف `loading.js`، يمكنك إضافة أي واجهة تحميل خفيفة الوزن. قد تجد أنه من المفيد استخدام [أدوات مطوري React](https://react.dev/learn/react-developer-tools) لتبديل حدود Suspense يدويًا. + +بشكل افتراضي، هذا الملف هو [مكون خادم](/docs/app/getting-started/server-and-client-components) - ولكن يمكن أيضًا استخدامه كمكون عميل من خلال التوجيه `"use client"`. + +## المرجع + +### المعاملات + +لا تقبل مكونات واجهة التحميل أي معاملات. + +## السلوك + +### التنقل + +- يتم [جلب واجهة Fallback مسبقًا](/docs/app/getting-started/linking-and-navigating#prefetching)، مما يجعل التنقل فوريًا ما لم يكتمل الجلب المسبق. +- التنقل قابل للمقاطعة، مما يعني أن تغيير المسارات لا يحتاج إلى انتظار تحميل محتوى المسار بالكامل قبل الانتقال إلى مسار آخر. +- تبقى التخطيطات المشتركة قابلة للتفاعل أثناء تحميل أجزاء المسار الجديدة. + +### حالات التحميل الفورية + +حالة التحميل الفورية هي واجهة Fallback التي تظهر فورًا عند التنقل. يمكنك تقديم مؤشرات تحميل مثل الهياكل العظمية والدوائر الدوارة، أو جزء صغير ولكن ذو معنى من الشاشات المستقبلية مثل صورة الغلاف والعنوان، إلخ. يساعد ذلك المستخدمين على فهم أن التطبيق يستجيب ويوفر تجربة مستخدم أفضل. + +قم بإنشاء حالة تحميل عن طريق إضافة ملف `loading.js` داخل مجلد. + +ملف loading.js الخاص + +```tsx filename="app/dashboard/loading.tsx" switcher +export default function Loading() { + // يمكنك إضافة أي واجهة داخل Loading، بما في ذلك هيكل عظمي. + return +} +``` + +```jsx filename="app/dashboard/loading.js" switcher +export default function Loading() { + // يمكنك إضافة أي واجهة داخل Loading، بما في ذلك هيكل عظمي. + return +} +``` + +في نفس المجلد، سيتم تداخل `loading.js` داخل `layout.js`. سيقوم تلقائيًا بلف ملف `page.js` وأي أطفال أدناه في حد ``. + +نظرة عامة على loading.js + +### تحسين محركات البحث (SEO) + +- سينتظر Next.js اكتمال جلب البيانات داخل [`generateMetadata`](/docs/app/api-reference/functions/generate-metadata) قبل بث الواجهة إلى العميل. يضمن هذا أن الجزء الأول من الاستجابة المبثوثة يتضمن علامات ``. +- نظرًا لأن البث يتم تقديمه من الخادم، فإنه لا يؤثر على تحسين محركات البحث. يمكنك استخدام أداة [Rich Results Test](https://search.google.com/test/rich-results) من Google لمعرفة كيفية ظهور صفحتك لمحركات بحث Google وعرض HTML المتسلسل ([المصدر](https://web.dev/rendering-on-the-web/#seo-considerations)). + +### رموز الحالة + +عند البث، سيتم إرجاع رمز حالة `200` للإشارة إلى نجاح الطلب. + +لا يزال بإمكان الخادم إبلاغ العميل بالأخطاء أو المشكلات داخل المحتوى المبثوث نفسه، على سبيل المثال عند استخدام [`redirect`](/docs/app/api-reference/functions/redirect) أو [`notFound`](/docs/app/api-reference/functions/not-found). نظرًا لأنه تم إرسال رؤوس الاستجابة بالفعل إلى العميل، لا يمكن تحديث رمز حالة الاستجابة. هذا لا يؤثر على تحسين محركات البحث. + +### حدود المتصفح + +[بعض المتصفحات](https://bugs.webkit.org/show_bug.cgi?id=252413) تقوم بتخزين مؤقت لاستجابة البث. قد لا ترى استجابة البث حتى تتجاوز الاستجابة 1024 بايت. هذا يؤثر عادةً فقط على تطبيقات "hello world"، وليس التطبيقات الحقيقية. + +## دعم المنصة + +| خيار النشر | مدعوم | +| ------------------------------------------------------------------- | ----------------- | +| [خادم Node.js](/docs/app/getting-started/deploying#nodejs-server) | نعم | +| [حاوية Docker](/docs/app/getting-started/deploying#docker) | نعم | +| [تصدير ثابت](/docs/app/getting-started/deploying#static-export) | لا | +| [المحولات](/docs/app/getting-started/deploying#adapters) | حسب المنصة | + +تعلم كيفية [تكوين البث](/docs/app/guides/self-hosting#streaming-and-suspense) عند استضافة Next.js ذاتيًا. + +## أمثلة + +### البث مع Suspense + +بالإضافة إلى `loading.js`، يمكنك أيضًا إنشاء حدود Suspense يدويًا لمكونات الواجهة الخاصة بك. يدعم موجه التطبيق البث باستخدام [Suspense](https://react.dev/reference/react/Suspense). + +يعمل `` عن طريق لف مكون يقوم بإجراء عمل غير متزامن (مثل جلب البيانات)، وعرض واجهة Fallback (مثل هيكل عظمي، دوارة) أثناء حدوثه، ثم استبدال مكونك بمجرد اكتمال الإجراء. + +```tsx filename="app/dashboard/page.tsx" switcher +import { Suspense } from 'react' +import { PostFeed, Weather } from './Components' + +export default function Posts() { + return ( +
+ جاري تحميل التغذية...

}> + +
+ جاري تحميل الطقس...

}> + +
+
+ ) +} +``` + +```jsx filename="app/dashboard/page.js" switcher +import { Suspense } from 'react' +import { PostFeed, Weather } from './Components' + +export default function Posts() { + return ( +
+ جاري تحميل التغذية...

}> + +
+ جاري تحميل الطقس...

}> + +
+
+ ) +} +``` + +باستخدام Suspense، تحصل على فوائد: + +1. **عرض الخادم التدريجي** - عرض HTML تدريجيًا من الخادم إلى العميل. +2. **الترطيب الانتقائي** - يعطي React الأولوية للمكونات التي يجب جعلها تفاعلية أولاً بناءً على تفاعل المستخدم. + +لمزيد من أمثلة Suspense وحالات الاستخدام، يرجى الاطلاع على [توثيق React](https://react.dev/reference/react/Suspense). + +## سجل الإصدارات + +| الإصدار | التغييرات | +| --------- | --------------------- | +| `v13.0.0` | تم تقديم `loading`. | \ No newline at end of file diff --git a/apps/docs/content/ar/docs/01-app/05-api-reference/03-file-conventions/mdx-components.mdx b/apps/docs/content/ar/docs/01-app/03-api-reference/03-file-conventions/mdx-components.mdx similarity index 100% rename from apps/docs/content/ar/docs/01-app/05-api-reference/03-file-conventions/mdx-components.mdx rename to apps/docs/content/ar/docs/01-app/03-api-reference/03-file-conventions/mdx-components.mdx diff --git a/apps/docs/content/ar/docs/01-app/03-building-your-application/01-routing/14-middleware.mdx b/apps/docs/content/ar/docs/01-app/03-api-reference/03-file-conventions/middleware.mdx similarity index 100% rename from apps/docs/content/ar/docs/01-app/03-building-your-application/01-routing/14-middleware.mdx rename to apps/docs/content/ar/docs/01-app/03-api-reference/03-file-conventions/middleware.mdx diff --git a/apps/docs/content/ar/docs/01-app/05-api-reference/03-file-conventions/page.mdx b/apps/docs/content/ar/docs/01-app/03-api-reference/03-file-conventions/page.mdx similarity index 100% rename from apps/docs/content/ar/docs/01-app/05-api-reference/03-file-conventions/page.mdx rename to apps/docs/content/ar/docs/01-app/03-api-reference/03-file-conventions/page.mdx diff --git a/apps/docs/content/ar/docs/01-app/05-api-reference/03-file-conventions/parallel-routes.mdx b/apps/docs/content/ar/docs/01-app/03-api-reference/03-file-conventions/parallel-routes.mdx similarity index 100% rename from apps/docs/content/ar/docs/01-app/05-api-reference/03-file-conventions/parallel-routes.mdx rename to apps/docs/content/ar/docs/01-app/03-api-reference/03-file-conventions/parallel-routes.mdx diff --git a/apps/docs/content/ar/docs/01-app/03-api-reference/03-file-conventions/public-folder.mdx b/apps/docs/content/ar/docs/01-app/03-api-reference/03-file-conventions/public-folder.mdx new file mode 100644 index 00000000..8fda3e5c --- /dev/null +++ b/apps/docs/content/ar/docs/01-app/03-api-reference/03-file-conventions/public-folder.mdx @@ -0,0 +1,47 @@ +--- +source-updated-at: 2025-08-09T22:43:46.028Z +translation-updated-at: 2025-08-09T22:43:46.028Z +title: مجلد public +nav_title: public +description: يتيح لك Next.js تقديم ملفات ثابتة مثل الصور في مجلد public. يمكنك معرفة كيفية عمل ذلك هنا. +--- + +{/* يتم مشاركة محتوى هذا المستند بين موجه التطبيق وموجه الصفحات. يمكنك استخدام مكون `Content` لإضافة محتوى خاص بموجه الصفحات. أي محتوى مشترك لا يجب أن يكون مغلفًا في مكون. */} + +يمكن لـ Next.js تقديم ملفات ثابتة مثل الصور من خلال مجلد يسمى `public` في الدليل الجذر. يمكن بعد ذلك الإشارة إلى الملفات داخل `public` من خلال الكود بدءًا من عنوان URL الأساسي (`/`). + +على سبيل المثال، يمكن عرض الملف `public/avatars/me.png` من خلال زيارة المسار `/avatars/me.png`. قد يبدو الكود لعرض تلك الصورة كما يلي: + +```jsx filename="avatar.js" +import Image from 'next/image' + +export function Avatar({ id, alt }) { + return {alt} +} + +export function AvatarOfMe() { + return +} +``` + +## التخزين المؤقت (Caching) + +لا يمكن لـ Next.js تخزين الأصول في مجلد `public` بشكل آمن لأنها قد تتغير. رؤوس التخزين المؤقت الافتراضية المطبقة هي: + +```jsx +Cache-Control: public, max-age=0 +``` + +## ملفات الروبوتات والأيقونات وغيرها + + + +المجلد مفيد أيضًا لملفات مثل `robots.txt`، `favicon.ico`، التحقق من موقع جوجل، وأي ملفات ثابتة أخرى (بما في ذلك `.html`). ولكن تأكد من عدم وجود ملف ثابت بنفس اسم ملف في مجلد `pages/`، لأن هذا سيؤدي إلى حدوث خطأ. [اقرأ المزيد](/docs/messages/conflicting-public-file-page). + + + + + +بالنسبة لملفات البيانات الوصفية الثابتة مثل `robots.txt`، `favicon.ico`، إلخ، يجب عليك استخدام [ملفات بيانات وصفية خاصة](/docs/app/api-reference/file-conventions/metadata) داخل مجلد `app`. + + \ No newline at end of file diff --git a/apps/docs/content/ar/docs/01-app/03-api-reference/03-file-conventions/route-groups.mdx b/apps/docs/content/ar/docs/01-app/03-api-reference/03-file-conventions/route-groups.mdx new file mode 100644 index 00000000..2d796e57 --- /dev/null +++ b/apps/docs/content/ar/docs/01-app/03-api-reference/03-file-conventions/route-groups.mdx @@ -0,0 +1,34 @@ +--- +source-updated-at: 2025-08-09T22:43:46.028Z +translation-updated-at: 2025-08-09T22:43:46.028Z +title: مجموعات المسارات (Route Groups) +description: يمكن استخدام مجموعات المسارات لتقسيم تطبيق Next.js الخاص بك إلى أقسام مختلفة. +--- + +مجموعات المسارات هي اصطلاح مجلدات يسمح لك بتنظيم المسارات حسب الفئة أو الفريق. + +## الاصطلاح + +يمكن إنشاء مجموعة مسارات عن طريق وضع اسم المجلد بين قوسين: `(اسم_المجلد)`. + +يشير هذا الاصطلاح إلى أن المجلد مخصص لأغراض تنظيمية ويجب **ألا يتم تضمينه** في مسار URL للمسار. + +مثال على هيكل المجلدات باستخدام مجموعات المسارات + +## حالات الاستخدام + +- تنظيم المسارات حسب الفريق أو الاهتمام أو الميزة. +- تعريف عدة [تخطيطات جذرية](/docs/app/api-reference/file-conventions/layout#root-layout). +- اختيار أجزاء مسار محددة لمشاركة تخطيط معين، مع استبعاد أجزاء أخرى. + +## محاذير + +- **تحميل الصفحة بالكامل**: إذا انتقلت بين مسارات تستخدم تخطيطات جذرية مختلفة، فسيؤدي ذلك إلى إعادة تحميل الصفحة بالكامل. على سبيل المثال، الانتقال من `/cart` الذي يستخدم `app/(shop)/layout.js` إلى `/blog` الذي يستخدم `app/(marketing)/layout.js`. هذا **ينطبق فقط** على تخطيطات الجذر المتعددة. +- **مسارات متضاربة**: لا ينبغي أن تحل المسارات في مجموعات مختلفة إلى نفس مسار URL. على سبيل المثال، `(marketing)/about/page.js` و `(shop)/about/page.js` سيحلان إلى `/about` مما سيسبب خطأ. +- **تخطيط الجذر الأساسي**: إذا كنت تستخدم عدة تخطيطات جذرية دون وجود ملف `layout.js` أساسي، تأكد من تعريف مسار الصفحة الرئيسية (/) ضمن إحدى مجموعات المسارات، مثل `app/(marketing)/page.js`. \ No newline at end of file diff --git a/apps/docs/content/ar/docs/01-app/05-api-reference/03-file-conventions/route-segment-config.mdx b/apps/docs/content/ar/docs/01-app/03-api-reference/03-file-conventions/route-segment-config.mdx similarity index 100% rename from apps/docs/content/ar/docs/01-app/05-api-reference/03-file-conventions/route-segment-config.mdx rename to apps/docs/content/ar/docs/01-app/03-api-reference/03-file-conventions/route-segment-config.mdx diff --git a/apps/docs/content/ar/docs/01-app/03-building-your-application/01-routing/13-route-handlers.mdx b/apps/docs/content/ar/docs/01-app/03-api-reference/03-file-conventions/route.mdx similarity index 100% rename from apps/docs/content/ar/docs/01-app/03-building-your-application/01-routing/13-route-handlers.mdx rename to apps/docs/content/ar/docs/01-app/03-api-reference/03-file-conventions/route.mdx diff --git a/apps/docs/content/ar/docs/01-app/03-api-reference/03-file-conventions/src-folder.mdx b/apps/docs/content/ar/docs/01-app/03-api-reference/03-file-conventions/src-folder.mdx new file mode 100644 index 00000000..c2ec92af --- /dev/null +++ b/apps/docs/content/ar/docs/01-app/03-api-reference/03-file-conventions/src-folder.mdx @@ -0,0 +1,37 @@ +--- +source-updated-at: 2025-08-09T22:43:46.028Z +translation-updated-at: 2025-08-09T22:43:46.028Z +title: مجلد src +nav_title: src +description: يمكنك حفظ الصفحات في مجلد `src` كبديل عن مجلد `pages` الرئيسي. +related: + links: + - app/getting-started/project-structure +--- + +{/* يتم مشاركة محتوى هذا المستند بين موجه التطبيق (app router) وموجه الصفحات (pages router). يمكنك استخدام المكون `المحتوى` لإضافة محتوى خاص بموجه الصفحات. أي محتوى مشترك لا يجب أن يكون مغلفًا بمكون. */} + +كبديل لوجود مجلدات `app` أو `pages` الخاصة بـ Next.js في جذر المشروع، يدعم Next.js أيضًا النمط الشائع لوضع كود التطبيق تحت مجلد `src`. + +هذا يفصل كود التطبيق عن ملفات إعدادات المشروع التي توجد غالبًا في جذر المشروع، وهو ما يفضله بعض الأفراد والفرق. + +لاستخدام مجلد `src`، انقل مجلد موجه التطبيق `app` أو مجلد موجه الصفحات `pages` إلى `src/app` أو `src/pages` على التوالي. + +مثال على هيكل المجلدات مع مجلد `src` + +> **معلومة مفيدة**: +> +> - يجب أن يبقى مجلد `/public` في جذر المشروع. +> - يجب أن تبقى ملفات الإعداد مثل `package.json` و `next.config.js` و `tsconfig.json` في جذر المشروع. +> - يجب أن تبقى ملفات `.env.*` في جذر المشروع. +> - سيتم تجاهل `src/app` أو `src/pages` إذا كان `app` أو `pages` موجودين في مجلد الجذر. +> - إذا كنت تستخدم `src`، فمن المحتمل أنك ستنقل مجلدات التطبيق الأخرى مثل `/components` أو `/lib`. +> - إذا كنت تستخدم Middleware، تأكد من وضعه داخل مجلد `src`. +> - إذا كنت تستخدم Tailwind CSS، ستحتاج إلى إضافة البادئة `/src` إلى ملف `tailwind.config.js` في [قسم content](https://tailwindcss.com/docs/content-configuration). +> - إذا كنت تستخدم مسارات TypeScript للاستيراد مثل `@/*`، يجب تحديث كائن `paths` في `tsconfig.json` ليشمل `src/`. \ No newline at end of file diff --git a/apps/docs/content/ar/docs/01-app/03-api-reference/03-file-conventions/template.mdx b/apps/docs/content/ar/docs/01-app/03-api-reference/03-file-conventions/template.mdx new file mode 100644 index 00000000..cde5eef9 --- /dev/null +++ b/apps/docs/content/ar/docs/01-app/03-api-reference/03-file-conventions/template.mdx @@ -0,0 +1,74 @@ +--- +source-updated-at: 2025-08-09T22:43:46.028Z +translation-updated-at: 2025-08-09T22:43:46.028Z +title: ملف template.js +description: مرجع API لملف template.js. +--- + +ملف **القالب (template)** يشبه [التخطيط (layout)](/docs/app/getting-started/layouts-and-pages#creating-a-layout) من حيث أنه يلف التخطيط أو الصفحة. على عكس التخطيطات التي تظل ثابتة عبر المسارات وتحافظ على الحالة، فإن القوالب تحصل على مفتاح فريد، مما يعني أن مكونات العميل (Client Components) التابعة لها تعيد تعيين حالتها عند التنقل. + +هي مفيدة عندما تحتاج إلى: + +- إعادة مزامنة `useEffect` عند التنقل. +- إعادة تعيين حالة مكونات العميل التابعة عند التنقل. على سبيل المثال، حقل إدخال. +- تغيير السلوك الافتراضي للإطار. على سبيل المثال، حدود Suspense داخل التخطيطات تظهر حالة الانتظار فقط عند التحميل الأول، بينما القوالب تظهرها في كل عملية تنقل. + +## الاصطلاح + +يمكن تعريف القالب عن طريق تصدير مكون React افتراضي من ملف `template.js`. يجب أن يقبل المكون خاصية `children`. + +ملف template.js الخاص + +```tsx filename="app/template.tsx" switcher +export default function Template({ children }: { children: React.ReactNode }) { + return
{children}
+} +``` + +```jsx filename="app/template.js" switcher +export default function Template({ children }) { + return
{children}
+} +``` + +من حيث التداخل، يتم عرض `template.js` بين التخطيط وأطفاله. إليك المخرجات المبسطة: + +```jsx filename="المخرجات" + + {/* لاحظ أن القالب يحصل على مفتاح فريد. */} + + +``` + +## الخصائص + +### `children` (مطلوبة) + +يقبل القالب خاصية `children`. + +```jsx filename="المخرجات" + + {/* لاحظ أن القالب يحصل تلقائيًا على مفتاح فريد. */} + + +``` + +## السلوك + +- **مكونات الخادم (Server Components)**: بشكل افتراضي، القوالب هي مكونات خادم. +- **إعادة التركيب عند التنقل**: تحصل القوالب على مفتاح فريد تلقائيًا. التنقل إلى مسار جديد يتسبب في إعادة تركيب القالب وأطفاله. +- **إعادة تعيين الحالة**: أي مكون عميل داخل القالب سيعيد تعيين حالته عند التنقل. +- **إعادة تشغيل التأثير (Effect)**: التأثيرات مثل `useEffect` ستتم مزامنتها مرة أخرى عند إعادة تركيب المكون. +- **إعادة إنشاء DOM**: يتم إعادة إنشاء عناصر DOM داخل القالب بالكامل. + +## سجل الإصدارات + +| الإصدار | التغييرات | +| --------- | ---------------------- | +| `v13.0.0` | تم تقديم `template`. | \ No newline at end of file diff --git a/apps/docs/content/ar/docs/01-app/03-api-reference/03-file-conventions/unauthorized.mdx b/apps/docs/content/ar/docs/01-app/03-api-reference/03-file-conventions/unauthorized.mdx new file mode 100644 index 00000000..85d20949 --- /dev/null +++ b/apps/docs/content/ar/docs/01-app/03-api-reference/03-file-conventions/unauthorized.mdx @@ -0,0 +1,116 @@ +--- +source-updated-at: 2025-08-09T22:43:46.028Z +translation-updated-at: 2025-08-09T22:43:46.028Z +title: unauthorized.js +description: مرجع API لملف unauthorized.js الخاص. +related: + links: + - app/api-reference/functions/unauthorized +version: experimental +--- + +يستخدم ملف **unauthorized** لعرض واجهة المستخدم عند استدعاء [دالة `unauthorized`](/docs/app/api-reference/functions/unauthorized) أثناء المصادقة. بالإضافة إلى السماح لك بتخصيص الواجهة، سيقوم Next.js بإرجاع رمز حالة `401`. + +```tsx filename="app/unauthorized.tsx" switcher +import Login from '@/app/components/Login' + +export default function Unauthorized() { + return ( +
+

401 - Unauthorized

+

Please log in to access this page.

+ +
+ ) +} +``` + +```jsx filename="app/unauthorized.js" switcher +import Login from '@/app/components/Login' + +export default function Unauthorized() { + return ( +
+

401 - Unauthorized

+

Please log in to access this page.

+ +
+ ) +} +``` + +## المرجع + +### الخصائص (Props) + +مكونات `unauthorized.js` لا تقبل أي خصائص. + +## أمثلة + +### عرض واجهة تسجيل الدخول للمستخدمين غير المصادق عليهم + +يمكنك استخدام [دالة `unauthorized`](/docs/app/api-reference/functions/unauthorized) لعرض ملف `unauthorized.js` مع واجهة تسجيل الدخول. + +```tsx filename="app/dashboard/page.tsx" switcher +import { verifySession } from '@/app/lib/dal' +import { unauthorized } from 'next/navigation' + +export default async function DashboardPage() { + const session = await verifySession() + + if (!session) { + unauthorized() + } + + return
Dashboard
+} +``` + +```jsx filename="app/dashboard/page.js" switcher +import { verifySession } from '@/app/lib/dal' +import { unauthorized } from 'next/navigation' + +export default async function DashboardPage() { + const session = await verifySession() + + if (!session) { + unauthorized() + } + + return
Dashboard
+} +``` + +```tsx filename="app/unauthorized.tsx" switcher +import Login from '@/app/components/Login' + +export default function UnauthorizedPage() { + return ( +
+

401 - Unauthorized

+

Please log in to access this page.

+ +
+ ) +} +``` + +```jsx filename="app/unauthorized.js" switcher +import Login from '@/app/components/Login' + +export default function UnauthorizedPage() { + return ( +
+

401 - Unauthorized

+

Please log in to access this page.

+ +
+ ) +} +``` + +## سجل الإصدارات + +| الإصدار | التغييرات | +| --------- | ----------------------------- | +| `v15.1.0` | تم إدخال `unauthorized.js`. | \ No newline at end of file diff --git a/apps/docs/content/ar/docs/01-app/05-api-reference/04-functions/after.mdx b/apps/docs/content/ar/docs/01-app/03-api-reference/04-functions/after.mdx similarity index 100% rename from apps/docs/content/ar/docs/01-app/05-api-reference/04-functions/after.mdx rename to apps/docs/content/ar/docs/01-app/03-api-reference/04-functions/after.mdx diff --git a/apps/docs/content/ar/docs/01-app/05-api-reference/04-functions/cacheLife.mdx b/apps/docs/content/ar/docs/01-app/03-api-reference/04-functions/cacheLife.mdx similarity index 100% rename from apps/docs/content/ar/docs/01-app/05-api-reference/04-functions/cacheLife.mdx rename to apps/docs/content/ar/docs/01-app/03-api-reference/04-functions/cacheLife.mdx diff --git a/apps/docs/content/ar/docs/01-app/05-api-reference/04-functions/cacheTag.mdx b/apps/docs/content/ar/docs/01-app/03-api-reference/04-functions/cacheTag.mdx similarity index 100% rename from apps/docs/content/ar/docs/01-app/05-api-reference/04-functions/cacheTag.mdx rename to apps/docs/content/ar/docs/01-app/03-api-reference/04-functions/cacheTag.mdx diff --git a/apps/docs/content/ar/docs/01-app/03-api-reference/04-functions/connection.mdx b/apps/docs/content/ar/docs/01-app/03-api-reference/04-functions/connection.mdx new file mode 100644 index 00000000..b63204df --- /dev/null +++ b/apps/docs/content/ar/docs/01-app/03-api-reference/04-functions/connection.mdx @@ -0,0 +1,60 @@ +--- +source-updated-at: 2025-08-09T22:43:46.028Z +translation-updated-at: 2025-08-09T22:43:46.028Z +title: اتصال +description: مرجع API لوظيفة الاتصال (connection). +--- + +تتيح لك وظيفة `connection()` الإشارة إلى أن العرض يجب أن ينتظر طلبًا واردا من المستخدم قبل المتابعة. + +هذه الوظيفة مفيدة عندما لا يستخدم المكون [واجهات برمجة التطبيقات الديناميكية](/docs/app/getting-started/partial-prerendering#dynamic-rendering)، ولكنك تريد أن يتم عرضه ديناميكيًا أثناء التشغيل وليس بشكل ثابت أثناء وقت البناء. يحدث هذا عادةً عندما تصل إلى معلومات خارجية تريد عمدًا أن تغير نتيجة العرض، مثل `Math.random()` أو `new Date()`. + +```ts filename="app/page.tsx" switcher +import { connection } from 'next/server' + +export default async function Page() { + await connection() + // كل ما يلي سيتم استبعاده من العرض المسبق + const rand = Math.random() + return {rand} +} +``` + +```jsx filename="app/page.js" switcher +import { connection } from 'next/server' + +export default async function Page() { + await connection() + // كل ما يلي سيتم استبعاده من العرض المسبق + const rand = Math.random() + return {rand} +} +``` + +## المرجع + +### النوع + +```jsx +function connection(): Promise +``` + +### المعاملات + +- لا تقبل الوظيفة أي معاملات. + +### القيم المُرجعة + +- تُرجع الوظيفة وعدًا (Promise) من النوع `void`. ليس المقصود استهلاك هذه القيمة. + +## معلومات مفيدة + +- تحل `connection` محل [`unstable_noStore`](/docs/app/api-reference/functions/unstable_noStore) لتصبح أكثر توافقًا مع مستقبل Next.js. +- تكون الوظيفة ضرورية فقط عندما يكون العرض الديناميكي مطلوبًا ولا تُستخدم واجهات برمجة التطبيقات الديناميكية الشائعة. + +### سجل الإصدارات + +| الإصدار | التغييرات | +| ------------ | ------------------------ | +| `v15.0.0` | أصبحت `connection` مستقرة. | +| `v15.0.0-RC` | تم تقديم `connection`. | \ No newline at end of file diff --git a/apps/docs/content/ar/docs/01-app/05-api-reference/04-functions/cookies.mdx b/apps/docs/content/ar/docs/01-app/03-api-reference/04-functions/cookies.mdx similarity index 100% rename from apps/docs/content/ar/docs/01-app/05-api-reference/04-functions/cookies.mdx rename to apps/docs/content/ar/docs/01-app/03-api-reference/04-functions/cookies.mdx diff --git a/apps/docs/content/ar/docs/01-app/05-api-reference/04-functions/draft-mode.mdx b/apps/docs/content/ar/docs/01-app/03-api-reference/04-functions/draft-mode.mdx similarity index 100% rename from apps/docs/content/ar/docs/01-app/05-api-reference/04-functions/draft-mode.mdx rename to apps/docs/content/ar/docs/01-app/03-api-reference/04-functions/draft-mode.mdx diff --git a/apps/docs/content/ar/docs/01-app/05-api-reference/04-functions/fetch.mdx b/apps/docs/content/ar/docs/01-app/03-api-reference/04-functions/fetch.mdx similarity index 100% rename from apps/docs/content/ar/docs/01-app/05-api-reference/04-functions/fetch.mdx rename to apps/docs/content/ar/docs/01-app/03-api-reference/04-functions/fetch.mdx diff --git a/apps/docs/content/ar/docs/01-app/05-api-reference/04-functions/forbidden.mdx b/apps/docs/content/ar/docs/01-app/03-api-reference/04-functions/forbidden.mdx similarity index 100% rename from apps/docs/content/ar/docs/01-app/05-api-reference/04-functions/forbidden.mdx rename to apps/docs/content/ar/docs/01-app/03-api-reference/04-functions/forbidden.mdx diff --git a/apps/docs/content/ar/docs/01-app/03-api-reference/04-functions/generate-image-metadata.mdx b/apps/docs/content/ar/docs/01-app/03-api-reference/04-functions/generate-image-metadata.mdx new file mode 100644 index 00000000..26ded1b0 --- /dev/null +++ b/apps/docs/content/ar/docs/01-app/03-api-reference/04-functions/generate-image-metadata.mdx @@ -0,0 +1,228 @@ +--- +source-updated-at: 2025-08-09T22:43:46.028Z +translation-updated-at: 2025-08-09T22:43:46.028Z +title: generateImageMetadata +description: تعلم كيفية إنشاء صور متعددة في ملف خاص واحد لواجهة برمجة تطبيقات البيانات الوصفية (Metadata API). +related: + title: الخطوات التالية + description: عرض جميع خيارات واجهة برمجة تطبيقات البيانات الوصفية. + links: + - app/api-reference/file-conventions/metadata +--- + +يمكنك استخدام `generateImageMetadata` لإنشاء إصدارات مختلفة من صورة واحدة أو إرجاع صور متعددة لقطاع مسار واحد. هذا مفيد عندما تريد تجنب ترميز قيم البيانات الوصفية بشكل ثابت، مثل الأيقونات. + +## المعاملات + +تقبل دالة `generateImageMetadata` المعاملات التالية: + +#### `params` (اختياري) + +كائن يحتوي على [معاملات المسار الديناميكي](/docs/app/api-reference/file-conventions/dynamic-routes) من القطاع الجذري وصولًا إلى القطاع الذي يتم استدعاء `generateImageMetadata` منه. + +```tsx filename="icon.tsx" switcher +export function generateImageMetadata({ + params, +}: { + params: { slug: string } +}) { + // ... +} +``` + +```jsx filename="icon.js" switcher +export function generateImageMetadata({ params }) { + // ... +} +``` + +| المسار | الرابط | `params` | +| ------------------------------- | ----------- | ------------------------- | +| `app/shop/icon.js` | `/shop` | `undefined` | +| `app/shop/[slug]/icon.js` | `/shop/1` | `{ slug: '1' }` | +| `app/shop/[tag]/[item]/icon.js` | `/shop/1/2` | `{ tag: '1', item: '2' }` | + +## القيم المُرجعة + +يجب أن ترجع دالة `generateImageMetadata` `مصفوفة` من الكائنات تحتوي على البيانات الوصفية للصورة مثل `alt` و `size`. بالإضافة إلى ذلك، يجب أن يتضمن كل عنصر قيمة `id` والتي سيتم تمريرها إلى خاصيات دالة إنشاء الصورة. + +| كائن البيانات الوصفية للصورة | النوع | +| --------------------- | ----------------------------------- | +| `id` | `string` (مطلوب) | +| `alt` | `string` | +| `size` | `{ width: number; height: number }` | +| `contentType` | `string` | + +```tsx filename="icon.tsx" switcher +import { ImageResponse } from 'next/og' + +export function generateImageMetadata() { + return [ + { + contentType: 'image/png', + size: { width: 48, height: 48 }, + id: 'small', + }, + { + contentType: 'image/png', + size: { width: 72, height: 72 }, + id: 'medium', + }, + ] +} + +export default function Icon({ id }: { id: string }) { + return new ImageResponse( + ( +
+ Icon {id} +
+ ) + ) +} +``` + +```jsx filename="icon.js" switcher +import { ImageResponse } from 'next/og' + +export function generateImageMetadata() { + return [ + { + contentType: 'image/png', + size: { width: 48, height: 48 }, + id: 'small', + }, + { + contentType: 'image/png', + size: { width: 72, height: 72 }, + id: 'medium', + }, + ] +} + +export default function Icon({ id }) { + return new ImageResponse( + ( +
+ Icon {id} +
+ ) + ) +} +``` + +### أمثلة + +#### استخدام بيانات خارجية + +يستخدم هذا المثال كائن `params` وبيانات خارجية لإنشاء صور متعددة [لـ Open Graph](/docs/app/api-reference/file-conventions/metadata/opengraph-image) لقطاع مسار. + +```tsx filename="app/products/[id]/opengraph-image.tsx" switcher +import { ImageResponse } from 'next/og' +import { getCaptionForImage, getOGImages } from '@/app/utils/images' + +export async function generateImageMetadata({ + params, +}: { + params: { id: string } +}) { + const images = await getOGImages(params.id) + + return images.map((image, idx) => ({ + id: idx, + size: { width: 1200, height: 600 }, + alt: image.text, + contentType: 'image/png', + })) +} + +export default async function Image({ + params, + id, +}: { + params: { id: string } + id: number +}) { + const productId = (await params).id + const imageId = id + const text = await getCaptionForImage(productId, imageId) + + return new ImageResponse( + ( +
+ {text} +
+ ) + ) +} +``` + +```jsx filename="app/products/[id]/opengraph-image.js" switcher +import { ImageResponse } from 'next/og' +import { getCaptionForImage, getOGImages } from '@/app/utils/images' + +export async function generateImageMetadata({ params }) { + const images = await getOGImages(params.id) + + return images.map((image, idx) => ({ + id: idx, + size: { width: 1200, height: 600 }, + alt: image.text, + contentType: 'image/png', + })) +} + +export default async function Image({ params, id }) { + const productId = (await params).id + const imageId = id + const text = await getCaptionForImage(productId, imageId) + + return new ImageResponse( + ( +
+ {text} +
+ ) + ) +} +``` + +## سجل الإصدارات + +| الإصدار | التغييرات | +| --------- | ----------------------------------- | +| `v13.3.0` | تم تقديم `generateImageMetadata`. | \ No newline at end of file diff --git a/apps/docs/content/ar/docs/01-app/05-api-reference/04-functions/generate-metadata.mdx b/apps/docs/content/ar/docs/01-app/03-api-reference/04-functions/generate-metadata.mdx similarity index 100% rename from apps/docs/content/ar/docs/01-app/05-api-reference/04-functions/generate-metadata.mdx rename to apps/docs/content/ar/docs/01-app/03-api-reference/04-functions/generate-metadata.mdx diff --git a/apps/docs/content/ar/docs/01-app/03-api-reference/04-functions/generate-sitemaps.mdx b/apps/docs/content/ar/docs/01-app/03-api-reference/04-functions/generate-sitemaps.mdx new file mode 100644 index 00000000..088ae39f --- /dev/null +++ b/apps/docs/content/ar/docs/01-app/03-api-reference/04-functions/generate-sitemaps.mdx @@ -0,0 +1,81 @@ +--- +source-updated-at: 2025-08-09T22:43:46.028Z +translation-updated-at: 2025-08-09T22:43:46.028Z +title: generateSitemaps +nav_title: generateSitemaps +description: تعرف على كيفية استخدام دالة generateSiteMaps لإنشاء خرائط مواقع متعددة لتطبيقك. +related: + title: الخطوات التالية + description: تعلم كيفية إنشاء خرائط مواقع لتطبيق Next.js الخاص بك. + links: + - app/api-reference/file-conventions/metadata/sitemap +--- + +يمكنك استخدام دالة `generateSitemaps` لإنشاء خرائط مواقع متعددة لتطبيقك. + +## القيم المُرجعة + +تُرجع دالة `generateSitemaps` مصفوفة من الكائنات تحتوي على خاصية `id`. + +## عناوين URL + +ستكون خرائط المواقع التي تم إنشاؤها متاحة على المسار `/.../sitemap/[id].xml`. على سبيل المثال، `/product/sitemap/1.xml`. + +## مثال + +على سبيل المثال، لتقسيم خريطة موقع باستخدام `generateSitemaps`، قم بإرجاع مصفوفة من الكائنات تحتوي على `id` لخريطة الموقع. ثم استخدم `id` لإنشاء خرائط المواقع الفريدة. + +```ts filename="app/product/sitemap.ts" switcher +import { BASE_URL } from '@/app/lib/constants' + +export async function generateSitemaps() { + // جلب العدد الإجمالي للمنتجات وحساب عدد خرائط المواقع المطلوبة + return [{ id: 0 }, { id: 1 }, { id: 2 }, { id: 3 }] +} + +export default async function sitemap({ + id, +}: { + id: number +}): Promise { + // الحد الأقصى لـ Google هو 50,000 عنوان URL لكل خريطة موقع + const start = id * 50000 + const end = start + 50000 + const products = await getProducts( + `SELECT id, date FROM products WHERE id BETWEEN ${start} AND ${end}` + ) + return products.map((product) => ({ + url: `${BASE_URL}/product/${product.id}`, + lastModified: product.date, + })) +} +``` + +```js filename="app/product/sitemap.js" switcher +import { BASE_URL } from '@/app/lib/constants' + +export async function generateSitemaps() { + // جلب العدد الإجمالي للمنتجات وحساب عدد خرائط المواقع المطلوبة + return [{ id: 0 }, { id: 1 }, { id: 2 }, { id: 3 }] +} + +export default async function sitemap({ id }) { + // الحد الأقصى لـ Google هو 50,000 عنوان URL لكل خريطة موقع + const start = id * 50000 + const end = start + 50000 + const products = await getProducts( + `SELECT id, date FROM products WHERE id BETWEEN ${start} AND ${end}` + ) + return products.map((product) => ({ + url: `${BASE_URL}/product/${id}`, + lastModified: product.date, + })) +} +``` + +## سجل الإصدارات + +| الإصدار | التغييرات | +| --------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- | +| `v15.0.0` | تقوم `generateSitemaps` الآن بإنشاء عناوين URL متسقة بين بيئة التطوير والإنتاج | +| `v13.3.2` | تم تقديم `generateSitemaps`. في بيئة التطوير، يمكنك عرض خريطة الموقع التي تم إنشاؤها على `/.../sitemap.xml/[id]`. على سبيل المثال، `/product/sitemap.xml/1`. | \ No newline at end of file diff --git a/apps/docs/content/ar/docs/01-app/05-api-reference/04-functions/generate-static-params.mdx b/apps/docs/content/ar/docs/01-app/03-api-reference/04-functions/generate-static-params.mdx similarity index 100% rename from apps/docs/content/ar/docs/01-app/05-api-reference/04-functions/generate-static-params.mdx rename to apps/docs/content/ar/docs/01-app/03-api-reference/04-functions/generate-static-params.mdx diff --git a/apps/docs/content/ar/docs/01-app/03-api-reference/04-functions/generate-viewport.mdx b/apps/docs/content/ar/docs/01-app/03-api-reference/04-functions/generate-viewport.mdx new file mode 100644 index 00000000..c80fef59 --- /dev/null +++ b/apps/docs/content/ar/docs/01-app/03-api-reference/04-functions/generate-viewport.mdx @@ -0,0 +1,239 @@ +--- +source-updated-at: 2025-08-09T22:43:46.028Z +translation-updated-at: 2025-08-09T22:43:46.028Z +title: generateViewport +description: مرجع API لوظيفة generateViewport. +related: + title: الخطوات التالية + description: عرض جميع خيارات Metadata API. + links: + - app/api-reference/file-conventions/metadata +--- + +يمكنك تخصيص منفذ العرض الأولي للصفحة باستخدام كائن `viewport` الثابت أو وظيفة `generateViewport` الديناميكية. + +> **معلومة مفيدة**: +> +> - تصديرات كائن `viewport` ووظيفة `generateViewport` **مدعومة فقط في مكونات الخادم (Server Components)**. +> - لا يمكنك تصدير كائن `viewport` ووظيفة `generateViewport` من نفس مقطع المسار. +> - إذا كنت تقوم بالترحيل من تصديرات `metadata`، يمكنك استخدام [أداة metadata-to-viewport-export codemod](/docs/app/guides/upgrading/codemods#metadata-to-viewport-export) لتحديث التغييرات الخاصة بك. + +## كائن `viewport` + +لتحديد خيارات منفذ العرض، قم بتصدير كائن `viewport` من ملف `layout.jsx` أو `page.jsx`. + +```tsx filename="layout.tsx | page.tsx" switcher +import type { Viewport } from 'next' + +export const viewport: Viewport = { + themeColor: 'black', +} + +export default function Page() {} +``` + +```jsx filename="layout.jsx | page.jsx" switcher +export const viewport = { + themeColor: 'black', +} + +export default function Page() {} +``` + +## وظيفة `generateViewport` + +يجب أن تُرجع `generateViewport` [كائن `Viewport`](#viewport-fields) يحتوي على حقل واحد أو أكثر من حقول منفذ العرض. + +```tsx filename="layout.tsx | page.tsx" switcher +export function generateViewport({ params }) { + return { + themeColor: '...', + } +} +``` + +```jsx filename="layout.js | page.js" switcher +export function generateViewport({ params }) { + return { + themeColor: '...', + } +} +``` + +> **معلومة مفيدة**: +> +> - إذا كان منفذ العرض لا يعتمد على معلومات وقت التشغيل، فيجب تحديده باستخدام كائن [`viewport` الثابت](#the-viewport-object) بدلاً من `generateViewport`. + +## حقول منفذ العرض + +### `themeColor` + +تعرف على المزيد حول [`theme-color`](https://developer.mozilla.org/docs/Web/HTML/Element/meta/name/theme-color). + +**لون المظهر البسيط** + +```tsx filename="layout.tsx | page.tsx" switcher +import type { Viewport } from 'next' + +export const viewport: Viewport = { + themeColor: 'black', +} +``` + +```jsx filename="layout.jsx | page.jsx" switcher +export const viewport = { + themeColor: 'black', +} +``` + +```html filename=" output" hideLineNumbers + +``` + +**مع سمة media** + +```tsx filename="layout.tsx | page.tsx" switcher +import type { Viewport } from 'next' + +export const viewport: Viewport = { + themeColor: [ + { media: '(prefers-color-scheme: light)', color: 'cyan' }, + { media: '(prefers-color-scheme: dark)', color: 'black' }, + ], +} +``` + +```jsx filename="layout.jsx | page.jsx" switcher +export const viewport = { + themeColor: [ + { media: '(prefers-color-scheme: light)', color: 'cyan' }, + { media: '(prefers-color-scheme: dark)', color: 'black' }, + ], +} +``` + +```html filename=" output" hideLineNumbers + + +``` + +### `width`، `initialScale`، `maximumScale` و `userScalable` + +> **معلومة مفيدة**: يتم تعيين وسم meta `viewport` تلقائيًا، وعادةً لا تكون هناك حاجة للتكوين اليدوي لأن الإعدادات الافتراضية كافية. ومع ذلك، يتم توفير المعلومات للاكتمال. + +```tsx filename="layout.tsx | page.tsx" switcher +import type { Viewport } from 'next' + +export const viewport: Viewport = { + width: 'device-width', + initialScale: 1, + maximumScale: 1, + userScalable: false, + // مدعوم أيضًا ولكن أقل استخدامًا + // interactiveWidget: 'resizes-visual', +} +``` + +```jsx filename="layout.jsx | page.jsx" switcher +export const viewport = { + width: 'device-width', + initialScale: 1, + maximumScale: 1, + userScalable: false, + // مدعوم أيضًا ولكن أقل استخدامًا + // interactiveWidget: 'resizes-visual', +} +``` + +```html filename=" output" hideLineNumbers + +``` + +### `colorScheme` + +تعرف على المزيد حول [`color-scheme`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/meta/name#:~:text=color%2Dscheme%3A%20specifies,of%20the%20following%3A). + +```tsx filename="layout.tsx | page.tsx" switcher +import type { Viewport } from 'next' + +export const viewport: Viewport = { + colorScheme: 'dark', +} +``` + +```jsx filename="layout.jsx | page.jsx" switcher +export const viewport = { + colorScheme: 'dark', +} +``` + +```html filename=" output" hideLineNumbers + +``` + +## الأنواع + +يمكنك إضافة أمان النوع إلى كائن منفذ العرض الخاص بك باستخدام النوع `Viewport`. إذا كنت تستخدم [الإضافة المدمجة لـ TypeScript](/docs/app/api-reference/config/typescript) في بيئة التطوير الخاصة بك، فلن تحتاج إلى إضافة النوع يدويًا، ولكن لا يزال بإمكانك إضافته صراحةً إذا كنت تريد. + +### كائن `viewport` + +```tsx +import type { Viewport } from 'next' + +export const viewport: Viewport = { + themeColor: 'black', +} +``` + +### وظيفة `generateViewport` + +#### وظيفة عادية + +```tsx +import type { Viewport } from 'next' + +export function generateViewport(): Viewport { + return { + themeColor: 'black', + } +} +``` + +#### مع خصائص المقطع + +```tsx +import type { Viewport } from 'next' + +type Props = { + params: Promise<{ id: string }> + searchParams: Promise<{ [key: string]: string | string[] | undefined }> +} + +export function generateViewport({ params, searchParams }: Props): Viewport { + return { + themeColor: 'black', + } +} + +export default function Page({ params, searchParams }: Props) {} +``` + +#### مشاريع JavaScript + +لمشاريع JavaScript، يمكنك استخدام JSDoc لإضافة أمان النوع. + +```js +/** @type {import("next").Viewport} */ +export const viewport = { + themeColor: 'black', +} +``` + +## سجل الإصدارات + +| الإصدار | التغييرات | +| --------- | --------------------------------------------- | +| `v14.0.0` | تم تقديم `viewport` و `generateViewport`. | \ No newline at end of file diff --git a/apps/docs/content/ar/docs/01-app/03-api-reference/04-functions/headers.mdx b/apps/docs/content/ar/docs/01-app/03-api-reference/04-functions/headers.mdx new file mode 100644 index 00000000..a2819ccf --- /dev/null +++ b/apps/docs/content/ar/docs/01-app/03-api-reference/04-functions/headers.mdx @@ -0,0 +1,75 @@ +--- +source-updated-at: 2025-08-09T22:43:46.028Z +translation-updated-at: 2025-08-09T22:43:46.028Z +title: headers +description: مرجع API لوظيفة `headers`. +--- + +`headers` هي وظيفة **غير متزامنة (async)** تتيح لك **قراءة** رؤوس طلب HTTP الواردة من [مكون الخادم (Server Component)](/docs/app/getting-started/server-and-client-components). + +```tsx filename="app/page.tsx" switcher +import { headers } from 'next/headers' + +export default async function Page() { + const headersList = await headers() + const userAgent = headersList.get('user-agent') +} +``` + +```jsx filename="app/page.js" switcher +import { headers } from 'next/headers' + +export default async function Page() { + const headersList = await headers() + const userAgent = headersList.get('user-agent') +} +``` + +## المرجع + +### المعاملات + +لا تأخذ `headers` أي معاملات. + +### القيم المُرجعة + +تُرجع `headers` كائن **للقراءة فقط** من نوع [Web Headers](https://developer.mozilla.org/docs/Web/API/Headers). + +- [`Headers.entries()`](https://developer.mozilla.org/docs/Web/API/Headers/entries): تُرجع [`iterator`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Iteration_protocols) يسمح بالمرور عبر جميع أزواج المفتاح/القيمة الموجودة في هذا الكائن. +- [`Headers.forEach()`](https://developer.mozilla.org/docs/Web/API/Headers/forEach): تنفذ دالة معينة مرة واحدة لكل زوج مفتاح/قيمة في كائن `Headers` هذا. +- [`Headers.get()`](https://developer.mozilla.org/docs/Web/API/Headers/get): تُرجع سلسلة نصية [`String`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) تحتوي على جميع قيم رأس معين داخل كائن `Headers`. +- [`Headers.has()`](https://developer.mozilla.org/docs/Web/API/Headers/has): تُرجع قيمة منطقية تشير إلى ما إذا كان كائن `Headers` يحتوي على رأس معين. +- [`Headers.keys()`](https://developer.mozilla.org/docs/Web/API/Headers/keys): تُرجع [`iterator`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Iteration_protocols) يسمح بالمرور عبر جميع مفاتيح أزواج المفتاح/القيمة في هذا الكائن. +- [`Headers.values()`](https://developer.mozilla.org/docs/Web/API/Headers/values): تُرجع [`iterator`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Iteration_protocols) يسمح بالمرور عبر جميع قيم أزواج المفتاح/القيمة في هذا الكائن. + +## معلومات مفيدة + +- `headers` هي وظيفة **غير متزامنة (async)** تُرجع promise. يجب استخدام `async/await` أو دالة [`use`](https://react.dev/reference/react/use) في React. + - في الإصدار 14 وما قبله، كانت `headers` وظيفة متزامنة. لدعم التوافق مع الإصدارات السابقة، لا يزال يمكن الوصول إليها بشكل متزامن في Next.js 15، ولكن هذا السلوك سيتم إهماله في المستقبل. +- نظرًا لأن `headers` للقراءة فقط، لا يمكنك `set` أو `delete` رؤوس الطلب الصادرة. +- `headers` هي [واجهة برمجة تطبيقات ديناميكية (Dynamic API)](/docs/app/getting-started/partial-prerendering#dynamic-rendering#dynamic-apis) لا يمكن معرفة قيمها مسبقًا. استخدامها سيؤدي إلى تحويل المسار إلى **[عرض ديناميكي (dynamic rendering)](/docs/app/getting-started/partial-prerendering#dynamic-rendering)**. + +## أمثلة + +### استخدام رأس Authorization + +```jsx filename="app/page.js" +import { headers } from 'next/headers' + +export default async function Page() { + const authorization = (await headers()).get('authorization') + const res = await fetch('...', { + headers: { authorization }, // تمرير رأس Authorization + }) + const user = await res.json() + + return

{user.name}

+} +``` + +## سجل الإصدارات + +| الإصدار | التغييرات | +| ------------ | ------------------------------------------------------------------------------------------------------ | +| `v15.0.0-RC` | أصبحت `headers` وظيفة غير متزامنة. يتوفر [أداة تحويل الشفرة (codemod)](/docs/app/guides/upgrading/codemods#150). | +| `v13.0.0` | تم تقديم `headers`. | \ No newline at end of file diff --git a/apps/docs/content/ar/docs/01-app/03-api-reference/04-functions/image-response.mdx b/apps/docs/content/ar/docs/01-app/03-api-reference/04-functions/image-response.mdx new file mode 100644 index 00000000..7cd0f2fb --- /dev/null +++ b/apps/docs/content/ar/docs/01-app/03-api-reference/04-functions/image-response.mdx @@ -0,0 +1,214 @@ +--- +source-updated-at: 2025-08-09T22:43:46.028Z +translation-updated-at: 2025-08-09T22:43:46.028Z +title: ImageResponse +description: مرجع API لـ مُنشئ ImageResponse. +--- + +يسمح لك مُنشئ `ImageResponse` بإنشاء صور ديناميكية باستخدام JSX وCSS. هذا مفيد لإنشاء صور وسائل التواصل الاجتماعي مثل صور Open Graph وبطاقات Twitter وغيرها. + +## المرجع + +### المعاملات + +المعاملات التالية متاحة لـ `ImageResponse`: + +```jsx +import { ImageResponse } from 'next/og' + +new ImageResponse( + element: ReactElement, + options: { + width?: number = 1200 + height?: number = 630 + emoji?: 'twemoji' | 'blobmoji' | 'noto' | 'openmoji' = 'twemoji', + fonts?: { + name: string, + data: ArrayBuffer, + weight: number, + style: 'normal' | 'italic' + }[] + debug?: boolean = false + + // خيارات سيتم تمريرها إلى استجابة HTTP + status?: number = 200 + statusText?: string + headers?: Record + }, +) +``` + +> تتوفر أمثلة في [Vercel OG Playground](https://og-playground.vercel.app/). + +### ميزات HTML وCSS المدعومة + +يدعم `ImageResponse` خصائص CSS الشائعة بما في ذلك flexbox والموضع المطلق، والخطوط المخصصة، ولف النص، والمركزة، والصور المتداخلة. + +يرجى الرجوع إلى [توثيق Satori](https://github.com/vercel/satori#css) للحصول على قائمة بميزات HTML وCSS المدعومة. + +## السلوك + +- يستخدم `ImageResponse` [@vercel/og](https://vercel.com/docs/concepts/functions/edge-functions/og-image-generation)، [Satori](https://github.com/vercel/satori)، وResvg لتحويل HTML وCSS إلى PNG. +- فقط flexbox ومجموعة فرعية من خصائص CSS مدعومة. التخطيطات المتقدمة (مثل `display: grid`) لن تعمل. +- الحد الأقصى لحجم الحزمة هو `500KB`. يشمل حجم الحزمة JSX الخاص بك، وCSS، والخطوط، والصور، وأي أصول أخرى. إذا تجاوزت الحد، فكر في تقليل حجم أي أصول أو جلبها أثناء التشغيل. +- فقط تنسيقات الخطوط `ttf`، `otf`، و`woff` مدعومة. لتعظيم سرعة تحليل الخط، يُفضل استخدام `ttf` أو `otf` بدلاً من `woff`. + +## أمثلة + +### معالجات المسار + +يمكن استخدام `ImageResponse` في معالجات المسار لإنشاء الصور ديناميكيًا في وقت الطلب. + +```js filename="app/api/route.js" +import { ImageResponse } from 'next/og' + +export async function GET() { + try { + return new ImageResponse( + ( +
+
+ Welcome to My Site +
+
+ Generated with Next.js ImageResponse +
+
+ ), + { + width: 1200, + height: 630, + } + ) + } catch (e) { + console.log(`${e.message}`) + return new Response(`Failed to generate the image`, { + status: 500, + }) + } +} +``` + +### البيانات الوصفية المستندة إلى الملف + +يمكنك استخدام `ImageResponse` في ملف [`opengraph-image.tsx`](/docs/app/api-reference/file-conventions/metadata/opengraph-image) لإنشاء صور Open Graph في وقت البناء أو ديناميكيًا في وقت الطلب. + +```tsx filename="app/opengraph-image.tsx" +import { ImageResponse } from 'next/og' + +// بيانات وصفية للصورة +export const alt = 'My site' +export const size = { + width: 1200, + height: 630, +} + +export const contentType = 'image/png' + +// إنشاء الصورة +export default async function Image() { + return new ImageResponse( + ( + // عنصر JSX لـ ImageResponse +
+ My site +
+ ), + // خيارات ImageResponse + { + // للراحة، يمكننا إعادة استخدام إعدادات حجم opengraph-image + // المصدرة لتعيين عرض وارتفاع ImageResponse أيضًا. + ...size, + } + ) +} +``` + +### خطوط مخصصة + +يمكنك استخدام خطوط مخصصة في `ImageResponse` الخاص بك عن طريق توفير مصفوفة `fonts` في الخيارات. + +```tsx filename="app/opengraph-image.tsx" +import { ImageResponse } from 'next/og' +import { readFile } from 'node:fs/promises' +import { join } from 'node:path' + +// بيانات وصفية للصورة +export const alt = 'My site' +export const size = { + width: 1200, + height: 630, +} + +export const contentType = 'image/png' + +// إنشاء الصورة +export default async function Image() { + // تحميل الخط، process.cwd() هو دليل مشروع Next.js + const interSemiBold = await readFile( + join(process.cwd(), 'assets/Inter-SemiBold.ttf') + ) + + return new ImageResponse( + ( + // ... + ), + // خيارات ImageResponse + { + // للراحة، يمكننا إعادة استخدام إعدادات حجم opengraph-image + // المصدرة لتعيين عرض وارتفاع ImageResponse أيضًا. + ...size, + fonts: [ + { + name: 'Inter', + data: interSemiBold, + style: 'normal', + weight: 400, + }, + ], + } + ) +} +``` + +## سجل الإصدارات + +| الإصدار | التغييرات | +| --------- | ----------------------------------------------------- | +| `v14.0.0` | تم نقل `ImageResponse` من `next/server` إلى `next/og` | +| `v13.3.0` | يمكن استيراد `ImageResponse` من `next/server`. | +| `v13.0.0` | تم تقديم `ImageResponse` عبر حزمة `@vercel/og`. | \ No newline at end of file diff --git a/apps/docs/content/ar/docs/01-app/03-api-reference/04-functions/index.mdx b/apps/docs/content/ar/docs/01-app/03-api-reference/04-functions/index.mdx new file mode 100644 index 00000000..c4a695ac --- /dev/null +++ b/apps/docs/content/ar/docs/01-app/03-api-reference/04-functions/index.mdx @@ -0,0 +1,8 @@ +--- +source-updated-at: 2025-08-09T22:43:46.028Z +translation-updated-at: 2025-08-09T22:43:46.028Z +title: الدوال +description: مرجع API لدوال وخطافات (Hooks) Next.js. +--- + +{/* يتم مشاركة محتوى هذا المستند بين موجه التطبيق (app router) وموجه الصفحات (pages router). يمكنك استخدام مكون `المحتوى` لإضافة محتوى خاص بموجه الصفحات. أي محتوى مشترك لا يجب أن يكون مغلفًا داخل مكون. */} \ No newline at end of file diff --git a/apps/docs/content/ar/docs/01-app/03-api-reference/04-functions/next-request.mdx b/apps/docs/content/ar/docs/01-app/03-api-reference/04-functions/next-request.mdx new file mode 100644 index 00000000..c6fc3bfe --- /dev/null +++ b/apps/docs/content/ar/docs/01-app/03-api-reference/04-functions/next-request.mdx @@ -0,0 +1,125 @@ +--- +source-updated-at: 2025-08-09T22:43:46.028Z +translation-updated-at: 2025-08-09T22:43:46.028Z +title: NextRequest +description: مرجع API لـ NextRequest. +--- + +{/* محتوى هذه الوثيقة مشترك بين موجه التطبيق وموجه الصفحات. يمكنك استخدام مكون `المحتوى` لإضافة محتوى خاص بموجه الصفحات. أي محتوى مشترك لا يجب أن يكون مغلفًا بمكون. */} + +تمتد NextRequest [واجهة برمجة تطبيقات الطلب على الويب (Web Request API)](https://developer.mozilla.org/docs/Web/API/Request) مع إضافة طرق إضافية لتسهيل الاستخدام. + +## `cookies` + +قراءة أو تعديل رأس [`Set-Cookie`](https://developer.mozilla.org/docs/Web/HTTP/Headers/Set-Cookie) للطلب. + +### `set(name, value)` + +بالنظر إلى اسم، يتم تعيين ملف تعريف الارتباط (cookie) بالقيمة المحددة على الطلب. + +```ts +// بالنظر إلى الطلب الوارد /home +// تعيين ملف تعريف الارتباط لإخفاء الشعار +// سيكون للطلب رأس `Set-Cookie:show-banner=false;path=/home` +request.cookies.set('show-banner', 'false') +``` + +### `get(name)` + +بالنظر إلى اسم ملف تعريف الارتباط، يتم إرجاع قيمة ملف تعريف الارتباط. إذا لم يتم العثور على ملف تعريف الارتباط، يتم إرجاع `undefined`. إذا تم العثور على عدة ملفات تعريف ارتباط، يتم إرجاع أول واحد. + +```ts +// بالنظر إلى الطلب الوارد /home +// { name: 'show-banner', value: 'false', Path: '/home' } +request.cookies.get('show-banner') +``` + +### `getAll()` + +بالنظر إلى اسم ملف تعريف الارتباط، يتم إرجاع قيم ملف تعريف الارتباط. إذا لم يتم تحديد اسم، يتم إرجاع جميع ملفات تعريف الارتباط على الطلب. + +```ts +// بالنظر إلى الطلب الوارد /home +// [ +// { name: 'experiments', value: 'new-pricing-page', Path: '/home' }, +// { name: 'experiments', value: 'winter-launch', Path: '/home' }, +// ] +request.cookies.getAll('experiments') +// بدلاً من ذلك، الحصول على جميع ملفات تعريف الارتباط للطلب +request.cookies.getAll() +``` + +### `delete(name)` + +بالنظر إلى اسم ملف تعريف الارتباط، يتم حذف ملف تعريف الارتباط من الطلب. + +```ts +// إرجاع true إذا تم الحذف، false إذا لم يتم حذف أي شيء +request.cookies.delete('experiments') +``` + +### `has(name)` + +بالنظر إلى اسم ملف تعريف الارتباط، يتم إرجاع `true` إذا كان ملف تعريف الارتباط موجودًا في الطلب. + +```ts +// إرجاع true إذا كان ملف تعريف الارتباط موجودًا، false إذا لم يكن موجودًا +request.cookies.has('experiments') +``` + +### `clear()` + +إزالة رأس `Set-Cookie` من الطلب. + +```ts +request.cookies.clear() +``` + +## `nextUrl` + +تمتد واجهة برمجة تطبيقات [`URL`](https://developer.mozilla.org/docs/Web/API/URL) الأصلية مع إضافة طرق إضافية لتسهيل الاستخدام، بما في ذلك خصائص خاصة بـ Next.js. + +```ts +// بالنظر إلى طلب إلى /home، pathname هو /home +request.nextUrl.pathname +// بالنظر إلى طلب إلى /home?name=lee، searchParams هو { 'name': 'lee' } +request.nextUrl.searchParams +``` + +الخيارات التالية متاحة: + + + +| الخاصية | النوع | الوصف | +| ----------------- | ------------------------- | --------------------------------------------------------------------------------------------------------------------------------- | +| `basePath` | `string` | [المسار الأساسي](/docs/pages/api-reference/config/next-config-js/basePath) لـ URL. | +| `buildId` | `string` \| `undefined` | معرّف بناء تطبيق Next.js. يمكن [تخصيصه](/docs/pages/api-reference/config/next-config-js/generateBuildId). | +| `defaultLocale` | `string` \| `undefined` | اللغة الافتراضية لـ [التدويل](/docs/pages/guides/internationalization). | +| `domainLocale` | | | +| - `defaultLocale` | `string` | اللغة الافتراضية داخل النطاق. | +| - `domain` | `string` | النطاق المرتبط بلغة محددة. | +| - `http` | `boolean` \| `undefined` | يشير إلى ما إذا كان النطاق يستخدم HTTP. | +| `locales` | `string[]` \| `undefined` | مصفوفة اللغات المتاحة. | +| `locale` | `string` \| `undefined` | اللغة النشطة حاليًا. | +| `url` | `URL` | كائن URL. | + + + + + +| الخاصية | النوع | الوصف | +| -------------- | ----------------------- | ------------------------------------------------------------------------------------------------------------------------------ | +| `basePath` | `string` | [المسار الأساسي](/docs/app/api-reference/config/next-config-js/basePath) لـ URL. | +| `buildId` | `string` \| `undefined` | معرّف بناء تطبيق Next.js. يمكن [تخصيصه](/docs/app/api-reference/config/next-config-js/generateBuildId). | +| `pathname` | `string` | مسار URL. | +| `searchParams` | `Object` | معلمات البحث لـ URL. | + +> **ملاحظة:** خصائص التدويل من موجه الصفحات غير متاحة للاستخدام في موجه التطبيق. تعلم المزيد عن [التدويل مع موجه التطبيق](/docs/app/guides/internationalization). + + + +## سجل الإصدارات + +| الإصدار | التغييرات | +| --------- | ----------------------- | +| `v15.0.0` | تم إزالة `ip` و `geo`. | \ No newline at end of file diff --git a/apps/docs/content/ar/docs/01-app/03-api-reference/04-functions/next-response.mdx b/apps/docs/content/ar/docs/01-app/03-api-reference/04-functions/next-response.mdx new file mode 100644 index 00000000..fd325a56 --- /dev/null +++ b/apps/docs/content/ar/docs/01-app/03-api-reference/04-functions/next-response.mdx @@ -0,0 +1,148 @@ +--- +source-updated-at: 2025-08-09T22:43:46.028Z +translation-updated-at: 2025-08-09T22:43:46.028Z +title: NextResponse +description: مرجع API لـ NextResponse. +--- + +{/* محتوى هذا المستند مشترك بين موجه التطبيق وموجه الصفحات. يمكنك استخدام مكون `المحتوى` لإضافة محتوى خاص بموجه الصفحات. أي محتوى مشترك لا يجب أن يكون مغلفًا بمكون. */} + +تمتد NextResponse [واجهة برمجة تطبيقات الاستجابة (Web Response API)](https://developer.mozilla.org/docs/Web/API/Response) مع إضافة طرق إضافية لتسهيل الاستخدام. + +## `cookies` + +قراءة أو تعديل رأس [`Set-Cookie`](https://developer.mozilla.org/docs/Web/HTTP/Headers/Set-Cookie) في الاستجابة. + +### `set(name, value)` + +بالنظر إلى اسم، يتم تعيين ملف تعريف الارتباط (cookie) بالقيمة المحددة في الاستجابة. + +```ts +// مع طلب وارد إلى /home +let response = NextResponse.next() +// تعيين ملف تعريف الارتباط لإخفاء اللافتة +response.cookies.set('show-banner', 'false') +// سيكون للاستجابة رأس `Set-Cookie:show-banner=false;path=/home` +return response +``` + +### `get(name)` + +بالنظر إلى اسم ملف تعريف الارتباط، يتم إرجاع قيمته. إذا لم يتم العثور على ملف تعريف الارتباط، يتم إرجاع `undefined`. إذا تم العثور على عدة ملفات تعريف ارتباط، يتم إرجاع أول واحد. + +```ts +// مع طلب وارد إلى /home +let response = NextResponse.next() +// { name: 'show-banner', value: 'false', Path: '/home' } +response.cookies.get('show-banner') +``` + +### `getAll()` + +بالنظر إلى اسم ملف تعريف الارتباط، يتم إرجاع قيم ملفات تعريف الارتباط. إذا لم يتم تحديد اسم، يتم إرجاع جميع ملفات تعريف الارتباط في الاستجابة. + +```ts +// مع طلب وارد إلى /home +let response = NextResponse.next() +// [ +// { name: 'experiments', value: 'new-pricing-page', Path: '/home' }, +// { name: 'experiments', value: 'winter-launch', Path: '/home' }, +// ] +response.cookies.getAll('experiments') +// بدلاً من ذلك، الحصول على جميع ملفات تعريف الارتباط للاستجابة +response.cookies.getAll() +``` + +### `delete(name)` + +بالنظر إلى اسم ملف تعريف الارتباط، يتم حذفه من الاستجابة. + +```ts +// مع طلب وارد إلى /home +let response = NextResponse.next() +// إرجاع true إذا تم الحذف، false إذا لم يتم حذف أي شيء +response.cookies.delete('experiments') +``` + +## `json()` + +إنشاء استجابة بجسم JSON معين. + +```ts filename="app/api/route.ts" switcher +import { NextResponse } from 'next/server' + +export async function GET(request: Request) { + return NextResponse.json({ error: 'Internal Server Error' }, { status: 500 }) +} +``` + +```js filename="app/api/route.js" switcher +import { NextResponse } from 'next/server' + +export async function GET(request) { + return NextResponse.json({ error: 'Internal Server Error' }, { status: 500 }) +} +``` + +## `redirect()` + +إنشاء استجابة تعيد التوجيه إلى [رابط URL](https://developer.mozilla.org/docs/Web/API/URL). + +```ts +import { NextResponse } from 'next/server' + +return NextResponse.redirect(new URL('/new', request.url)) +``` + +يمكن إنشاء [رابط URL](https://developer.mozilla.org/docs/Web/API/URL) وتعديله قبل استخدامه في طريقة `NextResponse.redirect()`. على سبيل المثال، يمكنك استخدام خاصية `request.nextUrl` للحصول على الرابط الحالي، ثم تعديله لإعادة التوجيه إلى رابط مختلف. + +```ts +import { NextResponse } from 'next/server' + +// مع طلب وارد... +const loginUrl = new URL('/login', request.url) +// إضافة ?from=/incoming-url إلى رابط /login +loginUrl.searchParams.set('from', request.nextUrl.pathname) +// وإعادة التوجيه إلى الرابط الجديد +return NextResponse.redirect(loginUrl) +``` + +## `rewrite()` + +إنشاء استجابة تعيد كتابة (توكيل) [رابط URL](https://developer.mozilla.org/docs/Web/API/URL) المحدد مع الحفاظ على الرابط الأصلي. + +```ts +import { NextResponse } from 'next/server' + +// الطلب الوارد: /about، المتصفح يعرض /about +// الطلب المعاد كتابته: /proxy، المتصفح يعرض /about +return NextResponse.rewrite(new URL('/proxy', request.url)) +``` + +## `next()` + +طريقة `next()` مفيدة في البرمجيات الوسيطة (Middleware)، حيث تسمح لك بالعودة مبكرًا ومتابعة التوجيه. + +```ts +import { NextResponse } from 'next/server' + +return NextResponse.next() +``` + +يمكنك أيضًا تمرير `headers` عند إنشاء الاستجابة: + +```ts +import { NextResponse } from 'next/server' + +// مع طلب وارد... +const newHeaders = new Headers(request.headers) +// إضافة رأس جديد +newHeaders.set('x-version', '123') +// وإنشاء استجابة مع الرؤوس الجديدة +return NextResponse.next({ + request: { + // رؤوس الطلب الجديدة + headers: newHeaders, + }, +}) +``` \ No newline at end of file diff --git a/apps/docs/content/ar/docs/01-app/03-api-reference/04-functions/not-found.mdx b/apps/docs/content/ar/docs/01-app/03-api-reference/04-functions/not-found.mdx new file mode 100644 index 00000000..96a40079 --- /dev/null +++ b/apps/docs/content/ar/docs/01-app/03-api-reference/04-functions/not-found.mdx @@ -0,0 +1,41 @@ +--- +source-updated-at: 2025-08-09T22:43:46.028Z +translation-updated-at: 2025-08-09T22:43:46.028Z +title: notFound +description: مرجع API لوظيفة `notFound`. +--- + +تتيح لك وظيفة `notFound` عرض [ملف `not-found`](/docs/app/api-reference/file-conventions/not-found) داخل مقطع مسار بالإضافة إلى حقن وسم ``. + +## `notFound()` + +استدعاء الدالة `notFound()` يرمي خطأ `NEXT_HTTP_ERROR_FALLBACK;404` ويوقف عرض مقطع المسار الذي تم رمي الخطأ فيه. يتيح لك تحديد [ملف **not-found**](/docs/app/api-reference/file-conventions/not-found) معالجة مثل هذه الأخطاء بطريقة أنيقة عن طريق عرض واجهة "غير موجود" داخل المقطع. + +```jsx filename="app/user/[id]/page.js" +import { notFound } from 'next/navigation' + +async function fetchUser(id) { + const res = await fetch('https://...') + if (!res.ok) return undefined + return res.json() +} + +export default async function Profile({ params }) { + const { id } = await params + const user = await fetchUser(id) + + if (!user) { + notFound() + } + + // ... +} +``` + +> **معلومة مفيدة**: لا تحتاج إلى استخدام `return notFound()` مع الدالة `notFound()` بسبب استخدام نوع [`never`](https://www.typescriptlang.org/docs/handbook/2/functions.html#never) في TypeScript. + +## سجل الإصدارات + +| الإصدار | التغييرات | +| --------- | ---------------------- | +| `v13.0.0` | تم إدخال `notFound`. | \ No newline at end of file diff --git a/apps/docs/content/ar/docs/01-app/05-api-reference/04-functions/permanentRedirect.mdx b/apps/docs/content/ar/docs/01-app/03-api-reference/04-functions/permanentRedirect.mdx similarity index 100% rename from apps/docs/content/ar/docs/01-app/05-api-reference/04-functions/permanentRedirect.mdx rename to apps/docs/content/ar/docs/01-app/03-api-reference/04-functions/permanentRedirect.mdx diff --git a/apps/docs/content/ar/docs/01-app/05-api-reference/04-functions/redirect.mdx b/apps/docs/content/ar/docs/01-app/03-api-reference/04-functions/redirect.mdx similarity index 100% rename from apps/docs/content/ar/docs/01-app/05-api-reference/04-functions/redirect.mdx rename to apps/docs/content/ar/docs/01-app/03-api-reference/04-functions/redirect.mdx diff --git a/apps/docs/content/ar/docs/01-app/05-api-reference/04-functions/unauthorized.mdx b/apps/docs/content/ar/docs/01-app/03-api-reference/04-functions/unauthorized.mdx similarity index 100% rename from apps/docs/content/ar/docs/01-app/05-api-reference/04-functions/unauthorized.mdx rename to apps/docs/content/ar/docs/01-app/03-api-reference/04-functions/unauthorized.mdx diff --git a/apps/docs/content/ar/docs/01-app/05-api-reference/04-functions/unstable_cache.mdx b/apps/docs/content/ar/docs/01-app/03-api-reference/04-functions/unstable_cache.mdx similarity index 100% rename from apps/docs/content/ar/docs/01-app/05-api-reference/04-functions/unstable_cache.mdx rename to apps/docs/content/ar/docs/01-app/03-api-reference/04-functions/unstable_cache.mdx diff --git a/apps/docs/content/ar/docs/01-app/03-api-reference/04-functions/unstable_noStore.mdx b/apps/docs/content/ar/docs/01-app/03-api-reference/04-functions/unstable_noStore.mdx new file mode 100644 index 00000000..2aa5c321 --- /dev/null +++ b/apps/docs/content/ar/docs/01-app/03-api-reference/04-functions/unstable_noStore.mdx @@ -0,0 +1,49 @@ +--- +source-updated-at: 2025-08-09T22:43:46.028Z +translation-updated-at: 2025-08-09T22:43:46.028Z +title: unstable_noStore +description: مرجع API لوظيفة unstable_noStore. +version: legacy +--- + +**في الإصدار 15، نوصي باستخدام [`connection`](/docs/app/api-reference/functions/connection) بدلاً من `unstable_noStore`.** + +يمكن استخدام `unstable_noStore` للانسحاب بشكل تصريحي من التصيير الثابت (static rendering) والإشارة إلى أن مكونًا معينًا لا يجب تخزينه مؤقتًا. + +```jsx +import { unstable_noStore as noStore } from 'next/cache'; + +export default async function ServerComponent() { + noStore(); + const result = await db.query(...); + ... +} +``` + +> **معلومة مفيدة**: +> +> - `unstable_noStore` يعادل `cache: 'no-store'` في `fetch` +> - يُفضل استخدام `unstable_noStore` بدلاً من `export const dynamic = 'force-dynamic'` لأنه أكثر دقة ويمكن استخدامه على أساس كل مكون + +- استخدام `unstable_noStore` داخل [`unstable_cache`](/docs/app/api-reference/functions/unstable_cache) لن يؤدي إلى الانسحاب من التوليد الثابت (static generation). بدلاً من ذلك، سيعتمد على تكوين الذاكرة المؤقتة لتحديد ما إذا كان سيتم تخزين النتيجة مؤقتًا أم لا. + +## الاستخدام + +إذا كنت تفضل عدم تمرير خيارات إضافية إلى `fetch`، مثل `cache: 'no-store'` أو `next: { revalidate: 0 }` أو في الحالات التي لا يكون فيها `fetch` متاحًا، يمكنك استخدام `noStore()` كبديل لكل هذه الحالات. + +```jsx +import { unstable_noStore as noStore } from 'next/cache'; + +export default async function ServerComponent() { + noStore(); + const result = await db.query(...); + ... +} +``` + +## سجل الإصدارات + +| الإصدار | التغييرات | +| --------- | ----------------------------------------------- | +| `v15.0.0` | تم إهمال `unstable_noStore` لصالح `connection`. | +| `v14.0.0` | تم تقديم `unstable_noStore`. | \ No newline at end of file diff --git a/apps/docs/content/ar/docs/01-app/05-api-reference/04-functions/unstable_rethrow.mdx b/apps/docs/content/ar/docs/01-app/03-api-reference/04-functions/unstable_rethrow.mdx similarity index 100% rename from apps/docs/content/ar/docs/01-app/05-api-reference/04-functions/unstable_rethrow.mdx rename to apps/docs/content/ar/docs/01-app/03-api-reference/04-functions/unstable_rethrow.mdx diff --git a/apps/docs/content/ar/docs/01-app/03-api-reference/04-functions/use-link-status.mdx b/apps/docs/content/ar/docs/01-app/03-api-reference/04-functions/use-link-status.mdx new file mode 100644 index 00000000..c42019f0 --- /dev/null +++ b/apps/docs/content/ar/docs/01-app/03-api-reference/04-functions/use-link-status.mdx @@ -0,0 +1,228 @@ +--- +source-updated-at: 2025-08-09T22:43:46.028Z +translation-updated-at: 2025-08-09T22:43:46.028Z +title: useLinkStatus +description: مرجع API لخطاف `useLinkStatus`. +related: + title: الخطوات التالية + description: تعلم المزيد عن الميزات المذكورة في هذه الصفحة من خلال قراءة مرجع API. + links: + - app/api-reference/components/link + - app/api-reference/file-conventions/loading +--- + +يتيح لك خطاف `useLinkStatus` تتبع الحالة **المعلقة** لمكون ``. يمكنك استخدامه لعرض ملاحظات بصرية مضمنة للمستخدم (مثل دوارات التحميل أو توهج النص) أثناء اكتمال الانتقال إلى مسار جديد. + +يكون `useLinkStatus` مفيدًا عندما: + +- يكون [الجلب المسبق](/docs/app/getting-started/linking-and-navigating#prefetching) معطلاً أو قيد التقدم مما يعني أن الانتقال محظور. +- يكون مسار الوجهة ديناميكيًا **ولا** يتضمن ملف [`loading.js`](/docs/app/api-reference/file-conventions/loading) الذي يسمح بالانتقال الفوري. + +```tsx filename="app/loading-indicator.tsx" switcher +'use client' + +import { useLinkStatus } from 'next/link' + +export default function LoadingIndicator() { + const { pending } = useLinkStatus() + return pending ? ( +
+ ) : null +} +``` + +```jsx filename="app/loading-indicator.js" switcher +'use client' + +import { useLinkStatus } from 'next/link' + +export default function LoadingIndicator() { + const { pending } = useLinkStatus() + return pending ? ( +
+ ) : null +} +``` + +```tsx filename="app/header.tsx" switcher +import Link from 'next/link' +import LoadingIndicator from './loading-indicator' + +export default function Header() { + return ( +
+ + Dashboard + +
+ ) +} +``` + +```jsx filename="app/header.js" switcher +import Link from 'next/link' +import LoadingIndicator from './loading-indicator' + +export default function Header() { + return ( +
+ + Dashboard + +
+ ) +} +``` + +> **معلومة مفيدة**: +> +> - يجب استخدام `useLinkStatus` داخل مكون فرعي لمكون `Link` +> - يكون الخطاف أكثر فائدة عند تعيين `prefetch={false}` على مكون `Link` +> - إذا تم جلب المسار المرتبط مسبقًا، سيتم تخطي الحالة المعلقة +> - عند النقر على عدة روابط بسرعة متتالية، يتم عرض الحالة المعلقة للرابط الأخير فقط +> - لا يتم دعم هذا الخطاف في موجه الصفحات وسيعود دائمًا بقيمة `{ pending: false }` + +## المعاملات + +```tsx +const { pending } = useLinkStatus() +``` + +لا يأخذ `useLinkStatus` أي معاملات. + +## القيم المعادة + +يُرجع `useLinkStatus` كائنًا يحتوي على خاصية واحدة: + +| الخاصية | النوع | الوصف | +| -------- | ------- | --------------------------------------- | +| pending | boolean | `true` قبل تحديث السجل، `false` بعده | + +## مثال + +### مؤشر تحميل مضمن + +من المفيد إضافة ملاحظات بصرية تشير إلى حدوث الانتقال في حال نقر المستخدم على رابط قبل اكتمال الجلب المسبق. + +```tsx filename="app/components/loading-indicator.tsx" switcher +'use client' + +import { useLinkStatus } from 'next/link' + +export default function LoadingIndicator() { + const { pending } = useLinkStatus() + return pending ? ( +
+ ) : null +} +``` + +```jsx filename="app/components/loading-indicator.js" switcher +'use client' + +import { useLinkStatus } from 'next/link' + +export default function LoadingIndicator() { + const { pending } = useLinkStatus() + return pending ? ( +
+ ) : null +} +``` + +```tsx filename="app/shop/layout.tsx" switcher +import Link from 'next/link' +import LoadingIndicator from './components/loading-indicator' + +const links = [ + { href: '/shop/electronics', label: 'Electronics' }, + { href: '/shop/clothing', label: 'Clothing' }, + { href: '/shop/books', label: 'Books' }, +] + +function Menubar() { + return ( +
+ {links.map((link) => ( + + {link.label} + + ))} +
+ ) +} + +export default function Layout({ children }: { children: React.ReactNode }) { + return ( +
+ + {children} +
+ ) +} +``` + +```jsx filename="app/shop/layout.js" switcher +import Link from 'next/link' +import LoadingIndicator from './components/loading-indicator' + +const links = [ + { href: '/shop/electronics', label: 'Electronics' }, + { href: '/shop/clothing', label: 'Clothing' }, + { href: '/shop/books', label: 'Books' }, +] + +function Menubar() { + return ( +
+ {links.map((link) => ( + + {link.label} + + ))} +
+ ) +} + +export default function Layout({ children }) { + return ( +
+ + {children} +
+ ) +} +``` + +## التعامل السلس مع الانتقال السريع + +إذا كان الانتقال إلى مسار جديد سريعًا، فقد يرى المستخدم وميضًا غير ضروري لمؤشر التحميل. إحدى طرق تحسين تجربة المستخدم وعرض مؤشر التحميل فقط عندما يستغرق الانتقال وقتًا أطول لإكماله هي إضافة تأخير أولي للرسوم المتحركة (مثل 100 مللي ثانية) وبدء الرسوم المتحركة كخفي (مثل `opacity: 0`). + +```css filename="app/styles/global.css" +.spinner { + /* ... */ + opacity: 0; + animation: + fadeIn 500ms 100ms forwards, + rotate 1s linear infinite; +} + +@keyframes fadeIn { + from { + opacity: 0; + } + to { + opacity: 1; + } +} + +@keyframes rotate { + to { + transform: rotate(360deg); + } +} +``` + +| الإصدار | التغييرات | +| --------- | --------------------------- | +| `v15.3.0` | تم تقديم `useLinkStatus`. | \ No newline at end of file diff --git a/apps/docs/content/ar/docs/01-app/03-api-reference/04-functions/use-params.mdx b/apps/docs/content/ar/docs/01-app/03-api-reference/04-functions/use-params.mdx new file mode 100644 index 00000000..fb1bc874 --- /dev/null +++ b/apps/docs/content/ar/docs/01-app/03-api-reference/04-functions/use-params.mdx @@ -0,0 +1,75 @@ +--- +source-updated-at: 2025-08-09T22:43:46.028Z +translation-updated-at: 2025-08-09T22:43:46.028Z +title: useParams +description: مرجع API لـ هوك `useParams`. +--- + +`useParams` هو هوك **مكون العميل (Client Component)** يسمح لك بقراءة [المعاملات الديناميكية (dynamic params)](/docs/app/api-reference/file-conventions/dynamic-routes) للطريق المملوءة بواسطة عنوان URL الحالي. + +```tsx filename="app/example-client-component.tsx" switcher +'use client' + +import { useParams } from 'next/navigation' + +export default function ExampleClientComponent() { + const params = useParams<{ tag: string; item: string }>() + + // Route -> /shop/[tag]/[item] + // URL -> /shop/shoes/nike-air-max-97 + // `params` -> { tag: 'shoes', item: 'nike-air-max-97' } + console.log(params) + + return '...' +} +``` + +```jsx filename="app/example-client-component.js" switcher +'use client' + +import { useParams } from 'next/navigation' + +export default function ExampleClientComponent() { + const params = useParams() + + // Route -> /shop/[tag]/[item] + // URL -> /shop/shoes/nike-air-max-97 + // `params` -> { tag: 'shoes', item: 'nike-air-max-97' } + console.log(params) + + return '...' +} +``` + +## المعاملات + +```tsx +const params = useParams() +``` + +لا يأخذ `useParams` أي معاملات. + +## القيم المُرجعة + +يُرجع `useParams` كائنًا يحتوي على [المعاملات الديناميكية (dynamic parameters)](/docs/app/api-reference/file-conventions/dynamic-routes) المملوءة للطريق الحالي. + +- كل خاصية في الكائن تمثل مقطعًا ديناميكيًا نشطًا. +- اسم الخاصية هو اسم المقطع، وقيمة الخاصية هي ما تم ملء المقطع به. +- ستكون قيمة الخاصية إما `string` أو مصفوفة من `string` اعتمادًا على [نوع المقطع الديناميكي](/docs/app/api-reference/file-conventions/dynamic-routes). +- إذا كان الطريق لا يحتوي على معاملات ديناميكية، يُرجع `useParams` كائنًا فارغًا. +- إذا تم استخدامه في Pages Router، سيُرجع `useParams` قيمة `null` عند التصيير الأولي ويتم تحديثه بالخصائص وفقًا للقواعد المذكورة أعلاه بمجرد أن يكون الموجه جاهزًا. + +على سبيل المثال: + +| الطريق | URL | `useParams()` | +| ------------------------------- | ----------- | ------------------------- | +| `app/shop/page.js` | `/shop` | `{}` | +| `app/shop/[slug]/page.js` | `/shop/1` | `{ slug: '1' }` | +| `app/shop/[tag]/[item]/page.js` | `/shop/1/2` | `{ tag: '1', item: '2' }` | +| `app/shop/[...slug]/page.js` | `/shop/1/2` | `{ slug: ['1', '2'] }` | + +## سجل الإصدارات + +| الإصدار | التغييرات | +| --------- | ----------------------- | +| `v13.3.0` | تم تقديم `useParams`. | \ No newline at end of file diff --git a/apps/docs/content/ar/docs/01-app/05-api-reference/04-functions/use-pathname.mdx b/apps/docs/content/ar/docs/01-app/03-api-reference/04-functions/use-pathname.mdx similarity index 100% rename from apps/docs/content/ar/docs/01-app/05-api-reference/04-functions/use-pathname.mdx rename to apps/docs/content/ar/docs/01-app/03-api-reference/04-functions/use-pathname.mdx diff --git a/apps/docs/content/ar/docs/01-app/03-api-reference/04-functions/use-report-web-vitals.mdx b/apps/docs/content/ar/docs/01-app/03-api-reference/04-functions/use-report-web-vitals.mdx new file mode 100644 index 00000000..dc2440dd --- /dev/null +++ b/apps/docs/content/ar/docs/01-app/03-api-reference/04-functions/use-report-web-vitals.mdx @@ -0,0 +1,246 @@ +--- +source-updated-at: 2025-08-09T22:43:46.028Z +translation-updated-at: 2025-08-09T22:43:46.028Z +title: استخدام useReportWebVitals +description: مرجع API لوظيفة useReportWebVitals. +--- + +{/* يتم مشاركة محتوى هذه الوثيقة بين موجّه التطبيق وموجّه الصفحات. يمكنك استخدام مكون `المحتوى` لإضافة محتوى خاص بموجّه الصفحات. أي محتوى مشترك لا يجب أن يكون مغلفًا بمكون. */} + +يتيح لك خطاف `useReportWebVitals` الإبلاغ عن [مؤشرات ويب الأساسية (Core Web Vitals)](https://web.dev/vitals/)، ويمكن استخدامه بالاشتراك مع خدمة التحليلات الخاصة بك. + +يتم استدعاء الوظائف الجديدة الممررة إلى `useReportWebVitals` مع المقاييس المتاحة حتى تلك اللحظة. لمنع الإبلاغ عن بيانات مكررة، تأكد من أن مرجع دالة رد الاتصال لا يتغير (كما هو موضح في أمثلة الكود أدناه). + + + +```jsx filename="pages/_app.js" +import { useReportWebVitals } from 'next/web-vitals' + +const logWebVitals = (metric) => { + console.log(metric) +} + +function MyApp({ Component, pageProps }) { + useReportWebVitals(logWebVitals) + + return +} +``` + + + + + +```jsx filename="app/_components/web-vitals.js" +'use client' + +import { useReportWebVitals } from 'next/web-vitals' + +const logWebVitals = (metric) => { + console.log(metric) +} + +export function WebVitals() { + useReportWebVitals(logWebVitals) + + return null +} +``` + +```jsx filename="app/layout.js" +import { WebVitals } from './_components/web-vitals' + +export default function Layout({ children }) { + return ( + + + + {children} + + + ) +} +``` + +> نظرًا لأن خطاف `useReportWebVitals` يتطلب توجيه `'use client'`، فإن النهج الأكثر كفاءة هو إنشاء مكون منفصل يستورده التخطيط الجذري. هذا يحصر حدود العميل حصريًا على مكون `WebVitals`. + + + +## useReportWebVitals + +يتكون كائن `metric` الممرر كوسيطة للخطاف من عدد من الخصائص: + +- `id`: معرف فريد للمقياس في سياق تحميل الصفحة الحالي +- `name`: اسم مقياس الأداء. القيم المحتملة تشمل أسماء مقاييس [مؤشرات ويب الأساسية](#web-vitals) (TTFB, FCP, LCP, FID, CLS) المحددة لتطبيق ويب. +- `delta`: الفرق بين القيمة الحالية والقيمة السابقة للمقياس. القيمة عادةً ما تكون بالمللي ثانية وتمثل التغيير في قيمة المقياس بمرور الوقت. +- `entries`: مصفوفة من [إدخالات الأداء (Performance Entries)](https://developer.mozilla.org/docs/Web/API/PerformanceEntry) المرتبطة بالمقياس. توفر هذه الإدخالات معلومات مفصلة حول أحداث الأداء المتعلقة بالمقياس. +- `navigationType`: يشير إلى [نوع التنقل (type of navigation)](https://developer.mozilla.org/docs/Web/API/PerformanceNavigationTiming/type) الذي أطلق جمع المقياس. القيم المحتملة تشمل `"navigate"`, `"reload"`, `"back_forward"`, و `"prerender"`. +- `rating`: تقييم نوعي لقيمة المقياس، يوفر تقييمًا للأداء. القيم المحتملة هي `"good"`, `"needs-improvement"`, و `"poor"`. يتم تحديد التقييم عادةً بمقارنة قيمة المقياس مع عتبات محددة مسبقًا تشير إلى أداء مقبول أو دون المستوى الأمثل. +- `value`: القيمة الفعلية أو مدة إدخال الأداء، عادةً بالمللي ثانية. توفر القيمة مقياسًا كميًا لجانب الأداء الذي يتم تتبعه بواسطة المقياس. يعتمد مصدر القيمة على المقياس المحدد الذي يتم قياسه ويمكن أن يأتي من واجهات [Performance API](https://developer.mozilla.org/docs/Web/API/Performance_API) المختلفة. + +## مؤشرات ويب الأساسية (Web Vitals) + +[مؤشرات ويب الأساسية (Web Vitals)](https://web.dev/vitals/) هي مجموعة من المقاييس المفيدة التي تهدف إلى التقاط تجربة المستخدم لصفحة ويب. تتضمن مؤشرات الويب الأساسية التالية: + +- [الوقت حتى أول بايت (Time to First Byte)](https://developer.mozilla.org/docs/Glossary/Time_to_first_byte) (TTFB) +- [الرسم الأول للمحتوى (First Contentful Paint)](https://developer.mozilla.org/docs/Glossary/First_contentful_paint) (FCP) +- [الرسم الأكبر للمحتوى (Largest Contentful Paint)](https://web.dev/lcp/) (LCP) +- [تأخر أول إدخال (First Input Delay)](https://web.dev/fid/) (FID) +- [الانزياح التراكمي للتخطيط (Cumulative Layout Shift)](https://web.dev/cls/) (CLS) +- [التفاعل حتى الرسم التالي (Interaction to Next Paint)](https://web.dev/inp/) (INP) + +يمكنك التعامل مع جميع نتائج هذه المقاييس باستخدام خاصية `name`. + + + +```jsx filename="pages/_app.js" +import { useReportWebVitals } from 'next/web-vitals' + +const handleWebVitals = (metric) => { + switch (metric.name) { + case 'FCP': { + // التعامل مع نتائج FCP + } + case 'LCP': { + // التعامل مع نتائج LCP + } + // ... + } +} + +function MyApp({ Component, pageProps }) { + useReportWebVitals(handleWebVitals) + + return +} +``` + + + + + +```tsx filename="app/components/web-vitals.tsx" switcher +'use client' + +import { useReportWebVitals } from 'next/web-vitals' + +type ReportWebVitalsCallback = Parameters[0] + +const handleWebVitals: ReportWebVitalsCallback = (metric) => { + switch (metric.name) { + case 'FCP': { + // التعامل مع نتائج FCP + } + case 'LCP': { + // التعامل مع نتائج LCP + } + // ... + } +} + +export function WebVitals() { + useReportWebVitals(handleWebVitals) +} +``` + +```jsx filename="app/components/web-vitals.js" switcher +'use client' + +import { useReportWebVitals } from 'next/web-vitals' + +const handleWebVitals = (metric) => { + switch (metric.name) { + case 'FCP': { + // التعامل مع نتائج FCP + } + case 'LCP': { + // التعامل مع نتائج LCP + } + // ... + } +} + +export function WebVitals() { + useReportWebVitals(handleWebVitals) +} +``` + + + + + +## مقاييس مخصصة + +بالإضافة إلى المقاييس الأساسية المذكورة أعلاه، هناك بعض المقاييس المخصصة الإضافية التي تقيس الوقت الذي تستغرقه الصفحة للترطيب (hydration) والرسم: + +- `Next.js-hydration`: طول الوقت الذي تستغرقه الصفحة لبدء وإنهاء الترطيب (بالملي ثانية) +- `Next.js-route-change-to-render`: طول الوقت الذي تستغرقه الصفحة لبدء الرسم بعد تغيير المسار (بالملي ثانية) +- `Next.js-render`: طول الوقت الذي تستغرقه الصفحة لإنهاء الرسم بعد تغيير المسار (بالملي ثانية) + +يمكنك التعامل مع جميع نتائج هذه المقاييس بشكل منفصل: + +```jsx filename="pages/_app.js" +import { useReportWebVitals } from 'next/web-vitals' + +function handleCustomMetrics(metrics) { + switch (metric.name) { + case 'Next.js-hydration': + // التعامل مع نتائج الترطيب + break + case 'Next.js-route-change-to-render': + // التعامل مع نتائج تغيير المسار إلى الرسم + break + case 'Next.js-render': + // التعامل مع نتائج الرسم + break + default: + break + } +} + +function MyApp({ Component, pageProps }) { + useReportWebVitals(handleCustomMetrics) + + return +} +``` + +تعمل هذه المقاييس في جميع المتصفحات التي تدعم [واجهة برمجة تطبيقات توقيت المستخدم (User Timing API)](https://caniuse.com/#feat=user-timing). + + + +## إرسال النتائج إلى أنظمة خارجية + +يمكنك إرسال النتائج إلى أي نقطة نهاية لقياس وتتبع أداء المستخدم الحقيقي على موقعك. على سبيل المثال: + +```js +function postWebVitals(metrics) { + const body = JSON.stringify(metric) + const url = 'https://example.com/analytics' + + // استخدم `navigator.sendBeacon()` إذا كان متاحًا، مع التراجع إلى `fetch()`. + if (navigator.sendBeacon) { + navigator.sendBeacon(url, body) + } else { + fetch(url, { body, method: 'POST', keepalive: true }) + } +} + +useReportWebVitals(postWebVitals) +``` + +> **من الجيد معرفة**: إذا كنت تستخدم [Google Analytics](https://analytics.google.com/analytics/web/)، فإن استخدام قيمة `id` يمكن أن يسمح لك ببناء توزيعات المقاييس يدويًا (لحساب النسب المئوية، إلخ.) + +> ```js +> useReportWebVitals(metric => { +> // استخدم `window.gtag` إذا قمت بتهيئة Google Analytics كما في هذا المثال: +> // https://github.com/vercel/next.js/blob/canary/examples/with-google-analytics +> window.gtag('event', metric.name, { +> value: Math.round(metric.name === 'CLS' ? metric.value * 1000 : metric.value), // يجب أن تكون القيم أعدادًا صحيحة +> event_label: metric.id, // معرف فريد لتحميل الصفحة الحالي +> non_interaction: true, // يتجنب التأثير على معدل الارتداد. +> }); +> } +> ``` +> +> اقرأ المزيد حول [إرسال النتائج إلى Google Analytics](https://github.com/GoogleChrome/web-vitals#send-the-results-to-google-analytics). \ No newline at end of file diff --git a/apps/docs/content/ar/docs/01-app/05-api-reference/04-functions/use-router.mdx b/apps/docs/content/ar/docs/01-app/03-api-reference/04-functions/use-router.mdx similarity index 100% rename from apps/docs/content/ar/docs/01-app/05-api-reference/04-functions/use-router.mdx rename to apps/docs/content/ar/docs/01-app/03-api-reference/04-functions/use-router.mdx diff --git a/apps/docs/content/ar/docs/01-app/05-api-reference/04-functions/use-search-params.mdx b/apps/docs/content/ar/docs/01-app/03-api-reference/04-functions/use-search-params.mdx similarity index 100% rename from apps/docs/content/ar/docs/01-app/05-api-reference/04-functions/use-search-params.mdx rename to apps/docs/content/ar/docs/01-app/03-api-reference/04-functions/use-search-params.mdx diff --git a/apps/docs/content/ar/docs/01-app/03-api-reference/04-functions/use-selected-layout-segment.mdx b/apps/docs/content/ar/docs/01-app/03-api-reference/04-functions/use-selected-layout-segment.mdx new file mode 100644 index 00000000..9ba6b3be --- /dev/null +++ b/apps/docs/content/ar/docs/01-app/03-api-reference/04-functions/use-selected-layout-segment.mdx @@ -0,0 +1,174 @@ +--- +source-updated-at: 2025-08-09T22:43:46.028Z +translation-updated-at: 2025-08-09T22:43:46.028Z +title: useSelectedLayoutSegment +description: مرجع API لـ hook استخدام useSelectedLayoutSegment. +--- + +`useSelectedLayoutSegment` هو hook **مكون العميل (Client Component)** الذي يسمح لك بقراءة مقطع المسار النشط **مستوى واحد أسفل** التخطيط الذي يتم استدعاؤه منه. + +هو مفيد لواجهة مستخدم التنقل، مثل علامات التبويب داخل التخطيط الرئيسي التي تغير النمط بناءً على مقطع الابن النشط. + +```tsx filename="app/example-client-component.tsx" switcher +'use client' + +import { useSelectedLayoutSegment } from 'next/navigation' + +export default function ExampleClientComponent() { + const segment = useSelectedLayoutSegment() + + return

Active segment: {segment}

+} +``` + +```jsx filename="app/example-client-component.js" switcher +'use client' + +import { useSelectedLayoutSegment } from 'next/navigation' + +export default function ExampleClientComponent() { + const segment = useSelectedLayoutSegment() + + return

Active segment: {segment}

+} +``` + +> **معلومة مفيدة**: +> +> - بما أن `useSelectedLayoutSegment` هو hook [مكون العميل (Client Component)](/docs/app/getting-started/server-and-client-components)، والتخطيطات هي [مكونات الخادم (Server Components)](/docs/app/getting-started/server-and-client-components) افتراضيًا، فإن `useSelectedLayoutSegment` عادةً ما يتم استدعاؤه عبر مكون عميل يتم استيراده إلى التخطيط. +> - `useSelectedLayoutSegment` يُرجع فقط المقطع مستوى واحد أسفل. لاسترجاع جميع المقاطع النشطة، راجع [`useSelectedLayoutSegments`](/docs/app/api-reference/functions/use-selected-layout-segments) + +## المعاملات + +```tsx +const segment = useSelectedLayoutSegment(parallelRoutesKey?: string) +``` + +`useSelectedLayoutSegment` يقبل *اختياريًا* [`parallelRoutesKey`](/docs/app/api-reference/file-conventions/parallel-routes#with-useselectedlayoutsegments)، مما يسمح لك بقراءة مقطع المسار النشط داخل تلك الفتحة. + +## القيم المُرجعة + +`useSelectedLayoutSegment` يُرجع سلسلة نصية للمقطع النشط أو `null` إذا لم يوجد. + +على سبيل المثال، بالنظر إلى التخطيطات وعناوين URL أدناه، سيكون المقطع المُرجع: + +| التخطيط | عنوان URL المزور | المقطع المُرجع | +| ------------------------- | ------------------------------ | ---------------- | +| `app/layout.js` | `/` | `null` | +| `app/layout.js` | `/dashboard` | `'dashboard'` | +| `app/dashboard/layout.js` | `/dashboard` | `null` | +| `app/dashboard/layout.js` | `/dashboard/settings` | `'settings'` | +| `app/dashboard/layout.js` | `/dashboard/analytics` | `'analytics'` | +| `app/dashboard/layout.js` | `/dashboard/analytics/monthly` | `'analytics'` | + +## أمثلة + +### إنشاء مكون رابط نشط + +يمكنك استخدام `useSelectedLayoutSegment` لإنشاء مكون رابط نشط يتغير نمطه بناءً على المقطع النشط. على سبيل المثال، قائمة مشاركات مميزة في الشريط الجانبي لمدونة: + +```tsx filename="app/blog/blog-nav-link.tsx" switcher +'use client' + +import Link from 'next/link' +import { useSelectedLayoutSegment } from 'next/navigation' + +// هذا المكون *العميل* سيتم استيراده إلى تخطيط المدونة +export default function BlogNavLink({ + slug, + children, +}: { + slug: string + children: React.ReactNode +}) { + // التنقل إلى `/blog/hello-world` سيرجع 'hello-world' + // لمقطع التخطيط المحدد + const segment = useSelectedLayoutSegment() + const isActive = slug === segment + + return ( + + {children} + + ) +} +``` + +```jsx filename="app/blog/blog-nav-link.js" switcher +'use client' + +import Link from 'next/link' +import { useSelectedLayoutSegment } from 'next/navigation' + +// هذا المكون *العميل* سيتم استيراده إلى تخطيط المدونة +export default function BlogNavLink({ slug, children }) { + // التنقل إلى `/blog/hello-world` سيرجع 'hello-world' + // لمقطع التخطيط المحدد + const segment = useSelectedLayoutSegment() + const isActive = slug === segment + + return ( + + {children} + + ) +} +``` + +```tsx filename="app/blog/layout.tsx" switcher +// استيراد مكون العميل إلى تخطيط رئيسي (مكون خادم) +import { BlogNavLink } from './blog-nav-link' +import getFeaturedPosts from './get-featured-posts' + +export default async function Layout({ + children, +}: { + children: React.ReactNode +}) { + const featuredPosts = await getFeaturedPosts() + return ( +
+ {featuredPosts.map((post) => ( +
+ {post.title} +
+ ))} +
{children}
+
+ ) +} +``` + +```jsx filename="app/blog/layout.js" switcher +// استيراد مكون العميل إلى تخطيط رئيسي (مكون خادم) +import { BlogNavLink } from './blog-nav-link' +import getFeaturedPosts from './get-featured-posts' + +export default async function Layout({ children }) { + const featuredPosts = await getFeaturedPosts() + return ( +
+ {featuredPosts.map((post) => ( +
+ {post.title} +
+ ))} +
{children}
+
+ ) +} +``` + +## سجل الإصدارات + +| الإصدار | التغييرات | +| --------- | -------------------------------------- | +| `v13.0.0` | تم تقديم `useSelectedLayoutSegment`. | \ No newline at end of file diff --git a/apps/docs/content/ar/docs/01-app/03-api-reference/04-functions/use-selected-layout-segments.mdx b/apps/docs/content/ar/docs/01-app/03-api-reference/04-functions/use-selected-layout-segments.mdx new file mode 100644 index 00000000..f3d0396b --- /dev/null +++ b/apps/docs/content/ar/docs/01-app/03-api-reference/04-functions/use-selected-layout-segments.mdx @@ -0,0 +1,79 @@ +--- +source-updated-at: 2025-08-09T22:43:46.028Z +translation-updated-at: 2025-08-09T22:43:46.028Z +title: useSelectedLayoutSegments +description: مرجع API لـ Hook استخدام useSelectedLayoutSegments. +--- + +`useSelectedLayoutSegments` هو **Hook لمكون العميل (Client Component)** يسمح لك بقراءة مقاطع المسار النشط **أسفل** التخطيط الذي يتم استدعاؤه منه. + +هذا مفيد لإنشاء واجهة المستخدم في التخطيطات الأم التي تحتاج إلى معرفة بالمقاطع الفرعية النشطة مثل مسارات التنقل (breadcrumbs). + +```tsx filename="app/example-client-component.tsx" switcher +'use client' + +import { useSelectedLayoutSegments } from 'next/navigation' + +export default function ExampleClientComponent() { + const segments = useSelectedLayoutSegments() + + return ( +
    + {segments.map((segment, index) => ( +
  • {segment}
  • + ))} +
+ ) +} +``` + +```jsx filename="app/example-client-component.js" switcher +'use client' + +import { useSelectedLayoutSegments } from 'next/navigation' + +export default function ExampleClientComponent() { + const segments = useSelectedLayoutSegments() + + return ( +
    + {segments.map((segment, index) => ( +
  • {segment}
  • + ))} +
+ ) +} +``` + +> **معلومة مفيدة**: +> +> - بما أن `useSelectedLayoutSegments` هو Hook لمكون العميل [Client Component](/docs/app/getting-started/server-and-client-components)، والتخطيطات هي [مكونات الخادم (Server Components)](/docs/app/getting-started/server-and-client-components) افتراضيًا، فإن `useSelectedLayoutSegments` عادةً ما يتم استدعاؤه عبر مكون عميل يتم استيراده إلى التخطيط. +> - المقاطع المُرجعة تتضمن [مجموعات المسار (Route Groups)](/docs/app/api-reference/file-conventions/route-groups)، والتي قد لا ترغب في تضمينها في واجهة المستخدم. يمكنك استخدام طريقة [`filter`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter) للمصفوفات لإزالة العناصر التي تبدأ بقوس. + +## المعاملات + +```tsx +const segments = useSelectedLayoutSegments(parallelRoutesKey?: string) +``` + +يقبل `useSelectedLayoutSegments` اختياريًا [`parallelRoutesKey`](/docs/app/api-reference/file-conventions/parallel-routes#with-useselectedlayoutsegments)، مما يسمح لك بقراءة مقطع المسار النشط داخل تلك الفتحة. + +## القيم المُرجعة + +يُرجع `useSelectedLayoutSegments` مصفوفة من السلاسل تحتوي على المقاطع النشطة بمستوى واحد أسفل التخطيط الذي تم استدعاء الـ Hook منه. أو مصفوفة فارغة إذا لم توجد أي مقاطع. + +على سبيل المثال، بالنظر إلى التخطيطات وعناوين URL أدناه، ستكون المقاطع المُرجعة: + +| التخطيط | عنوان URL المزور | المقاطع المُرجعة | +| ------------------------- | --------------------- | --------------------------- | +| `app/layout.js` | `/` | `[]` | +| `app/layout.js` | `/dashboard` | `['dashboard']` | +| `app/layout.js` | `/dashboard/settings` | `['dashboard', 'settings']` | +| `app/dashboard/layout.js` | `/dashboard` | `[]` | +| `app/dashboard/layout.js` | `/dashboard/settings` | `['settings']` | + +## سجل الإصدارات + +| الإصدار | التغييرات | +| --------- | --------------------------------------- | +| `v13.0.0` | تم إدخال `useSelectedLayoutSegments`. | \ No newline at end of file diff --git a/apps/docs/content/ar/docs/01-app/03-api-reference/04-functions/userAgent.mdx b/apps/docs/content/ar/docs/01-app/03-api-reference/04-functions/userAgent.mdx new file mode 100644 index 00000000..156703d0 --- /dev/null +++ b/apps/docs/content/ar/docs/01-app/03-api-reference/04-functions/userAgent.mdx @@ -0,0 +1,81 @@ +--- +source-updated-at: 2025-08-09T22:43:46.028Z +translation-updated-at: 2025-08-09T22:43:46.028Z +title: userAgent +description: أداة `userAgent` تمد واجهة برمجة تطبيقات الويب (Web Request API) بخصائص وطرق إضافية للتفاعل مع كائن وكيل المستخدم من الطلب. +--- + +{/* محتوى هذه الوثيقة مشترك بين موجه التطبيق وموجه الصفحات. يمكنك استخدام مكون `محتوى` لإضافة محتوى خاص بموجه الصفحات. أي محتوى مشترك يجب ألا يكون مغلفًا في مكون. */} + +أداة `userAgent` تمد [واجهة برمجة تطبيقات الويب (Web Request API)](https://developer.mozilla.org/docs/Web/API/Request) بخصائص وطرق إضافية للتفاعل مع كائن وكيل المستخدم من الطلب. + +```ts filename="middleware.ts" switcher +import { NextRequest, NextResponse, userAgent } from 'next/server' + +export function middleware(request: NextRequest) { + const url = request.nextUrl + const { device } = userAgent(request) + + // device.type يمكن أن يكون: 'mobile', 'tablet', 'console', 'smarttv', + // 'wearable', 'embedded', أو غير محدد (لمتصفحات سطح المكتب) + const viewport = device.type || 'desktop' + + url.searchParams.set('viewport', viewport) + return NextResponse.rewrite(url) +} +``` + +```js filename="middleware.js" switcher +import { NextResponse, userAgent } from 'next/server' + +export function middleware(request) { + const url = request.nextUrl + const { device } = userAgent(request) + + // device.type يمكن أن يكون: 'mobile', 'tablet', 'console', 'smarttv', + // 'wearable', 'embedded', أو غير محدد (لمتصفحات سطح المكتب) + const viewport = device.type || 'desktop' + + url.searchParams.set('viewport', viewport) + return NextResponse.rewrite(url) +} +``` + +## `isBot` + +قيمة منطقية تشير إلى ما إذا كان الطلب قادمًا من بوت معروف. + +## `browser` + +كائن يحتوي على معلومات حول المتصفح المستخدم في الطلب. + +- `name`: سلسلة تمثل اسم المتصفح، أو `undefined` إذا لم يتم التعرف عليه. +- `version`: سلسلة تمثل إصدار المتصفح، أو `undefined`. + +## `device` + +كائن يحتوي على معلومات حول الجهاز المستخدم في الطلب. + +- `model`: سلسلة تمثل نموذج الجهاز، أو `undefined`. +- `type`: سلسلة تمثل نوع الجهاز، مثل `console`, `mobile`, `tablet`, `smarttv`, `wearable`, `embedded`, أو `undefined`. +- `vendor`: سلسلة تمثل الشركة المصنعة للجهاز، أو `undefined`. + +## `engine` + +كائن يحتوي على معلومات حول محرك المتصفح. + +- `name`: سلسلة تمثل اسم المحرك. القيم الممكنة تشمل: `Amaya`, `Blink`, `EdgeHTML`, `Flow`, `Gecko`, `Goanna`, `iCab`, `KHTML`, `Links`, `Lynx`, `NetFront`, `NetSurf`, `Presto`, `Tasman`, `Trident`, `w3m`, `WebKit` أو `undefined`. +- `version`: سلسلة تمثل إصدار المحرك، أو `undefined`. + +## `os` + +كائن يحتوي على معلومات حول نظام التشغيل. + +- `name`: سلسلة تمثل اسم نظام التشغيل، أو `undefined`. +- `version`: سلسلة تمثل إصدار نظام التشغيل، أو `undefined`. + +## `cpu` + +كائن يحتوي على معلومات حول بنية المعالج. + +- `architecture`: سلسلة تمثل بنية المعالج. القيم الممكنة تشمل: `68k`, `amd64`, `arm`, `arm64`, `armhf`, `avr`, `ia32`, `ia64`, `irix`, `irix64`, `mips`, `mips64`, `pa-risc`, `ppc`, `sparc`, `sparc64` أو `undefined` \ No newline at end of file diff --git a/apps/docs/content/ar/docs/01-app/03-api-reference/05-config/01-next-config-js/allowedDevOrigins.mdx b/apps/docs/content/ar/docs/01-app/03-api-reference/05-config/01-next-config-js/allowedDevOrigins.mdx new file mode 100644 index 00000000..a1e7a9f4 --- /dev/null +++ b/apps/docs/content/ar/docs/01-app/03-api-reference/05-config/01-next-config-js/allowedDevOrigins.mdx @@ -0,0 +1,20 @@ +--- +source-updated-at: 2025-08-09T22:43:46.028Z +translation-updated-at: 2025-08-09T22:43:46.028Z +title: allowedDevOrigins +description: استخدم `allowedDevOrigins` لتكوين أصول إضافية يمكنها طلب خادم التطوير. +--- + +{/* يتم مشاركة محتوى هذا المستند بين موجِّه التطبيق وموجِّه الصفحات. يمكنك استخدام مكون `المحتوى` لإضافة محتوى خاص بموجِّه الصفحات. أي محتوى مشترك لا يجب أن يكون مغلفًا بمكون. */} + +لا يقوم Next.js بحظر طلبات الأصول المتقاطعة (cross-origin) تلقائيًا أثناء التطوير، ولكنه سيقوم بالحظر افتراضيًا في إصدار رئيسي مستقبلي من Next.js لمنع الطلبات غير المصرح بها للأصول/النقاط الطرفية الداخلية المتاحة في وضع التطوير. + +لتكوين تطبيق Next.js للسماح بطلبات من أصول أخرى غير اسم المضيف الذي تم تهيئة الخادم به (`localhost` افتراضيًا)، يمكنك استخدام خيار التكوين `allowedDevOrigins`. + +يسمح لك `allowedDevOrigins` بتعيين أصول إضافية يمكن استخدامها في وضع التطوير. على سبيل المثال، لاستخدام `local-origin.dev` بدلاً من `localhost` فقط، افتح ملف `next.config.js` وأضف تكوين `allowedDevOrigins`: + +```js filename="next.config.js" +module.exports = { + allowedDevOrigins: ['local-origin.dev', '*.local-origin.dev'], +} +``` \ No newline at end of file diff --git a/apps/docs/content/ar/docs/01-app/05-api-reference/05-config/01-next-config-js/appDir.mdx b/apps/docs/content/ar/docs/01-app/03-api-reference/05-config/01-next-config-js/appDir.mdx similarity index 100% rename from apps/docs/content/ar/docs/01-app/05-api-reference/05-config/01-next-config-js/appDir.mdx rename to apps/docs/content/ar/docs/01-app/03-api-reference/05-config/01-next-config-js/appDir.mdx diff --git a/apps/docs/content/ar/docs/01-app/03-api-reference/05-config/01-next-config-js/assetPrefix.mdx b/apps/docs/content/ar/docs/01-app/03-api-reference/05-config/01-next-config-js/assetPrefix.mdx new file mode 100644 index 00000000..93aaaadc --- /dev/null +++ b/apps/docs/content/ar/docs/01-app/03-api-reference/05-config/01-next-config-js/assetPrefix.mdx @@ -0,0 +1,77 @@ +--- +source-updated-at: 2025-08-09T22:43:46.028Z +translation-updated-at: 2025-08-09T22:43:46.028Z +title: assetPrefix +description: تعرف على كيفية استخدام خيار التكوين assetPrefix لضبط شبكة توصيل المحتوى (CDN) الخاصة بك. +--- + +{/* المحتوى في هذا المستند مشترك بين موجه التطبيق وموجه الصفحات. يمكنك استخدام مكون `المحتوى` لإضافة محتوى خاص بموجه الصفحات. أي محتوى مشترك يجب ألا يكون مغلفًا داخل مكون. */} + + + +> **ملاحظة**: [النشر على Vercel](/docs/app/getting-started/deploying) يقوم تلقائيًا بضبط شبكة توصيل محتوى (CDN) عالمية لمشروع Next.js الخاص بك. +> لا تحتاج إلى إعداد بادئة الأصول (Asset Prefix) يدويًا. + + + + + +> **ملاحظة**: [النشر على Vercel](/docs/pages/getting-started/deploying) يقوم تلقائيًا بضبط شبكة توصيل محتوى (CDN) عالمية لمشروع Next.js الخاص بك. +> لا تحتاج إلى إعداد بادئة الأصول (Asset Prefix) يدويًا. + + + +> **معلومة مفيدة**: بدءًا من Next.js 9.5+ تمت إضافة دعم لـ [مسار الأساس (Base Path)](/docs/app/api-reference/config/next-config-js/basePath) القابل للتخصيص، والذي يكون أكثر ملاءمة لاستضافة تطبيقك على مسار فرعي مثل `/docs`. +> لا ننصح باستخدام بادئة أصول مخصصة لهذا الغرض. + +## إعداد شبكة توصيل المحتوى (CDN) + +لإعداد [شبكة توصيل المحتوى (CDN)](https://en.wikipedia.org/wiki/Content_delivery_network)، يمكنك ضبط بادئة الأصول وتكوين أصل CDN الخاص بك ليحل إلى النطاق الذي يستضيف Next.js. + +افتح ملف `next.config.mjs` وأضف تكوين `assetPrefix` بناءً على [المرحلة](/docs/app/api-reference/config/next-config-js#async-configuration): + +```js filename="next.config.mjs" +// @ts-check +import { PHASE_DEVELOPMENT_SERVER } from 'next/constants' + +export default (phase) => { + const isDev = phase === PHASE_DEVELOPMENT_SERVER + /** + * @type {import('next').NextConfig} + */ + const nextConfig = { + assetPrefix: isDev ? undefined : 'https://cdn.mydomain.com', + } + return nextConfig +} +``` + +سيستخدم Next.js تلقائيًا بادئة الأصول الخاصة بك لملفات JavaScript و CSS التي يتم تحميلها من المسار `/_next/` (مجلد `.next/static/`). على سبيل المثال، مع التكوين أعلاه، طلب جزء JS التالي: + +``` +/_next/static/chunks/4b9b41aaa062cbbfeff4add70f256968c51ece5d.4d708494b3aed70c04f0.js +``` + +سيصبح بدلاً من ذلك: + +``` +https://cdn.mydomain.com/_next/static/chunks/4b9b41aaa062cbbfeff4add70f256968c51ece5d.4d708494b3aed70c04f0.js +``` + +سيعتمد التكوين الدقيق لرفع ملفاتك إلى CDN معين على CDN الذي تختاره. المجلد الوحيد الذي تحتاج إلى استضافته على CDN الخاص بك هو محتويات `.next/static/`، والتي يجب رفعها كـ `_next/static/` كما يشير عنوان URL أعلاه. **لا ترفع بقية مجلد `.next/` الخاص بك**، حيث لا يجب تعريض كود الخادم الخاص بك والتكوينات الأخرى للعامة. + +بينما تغطي `assetPrefix` طلبات `_next/static`، إلا أنها لا تؤثر على المسارات التالية: + + + +- الملفات في مجلد [public](/docs/app/api-reference/file-conventions/public-folder)؛ إذا كنت تريد تقديم هذه الأصول عبر CDN، فسيتعين عليك إضافة البادئة بنفسك + + + + + +- الملفات في مجلد [public](/docs/pages/api-reference/file-conventions/public-folder)؛ إذا كنت تريد تقديم هذه الأصول عبر CDN، فسيتعين عليك إضافة البادئة بنفسك +- طلبات `/_next/data/` لصفحات `getServerSideProps`. هذه الطلبات ستتم دائمًا ضد النطاق الرئيسي لأنها ليست ثابتة. +- طلبات `/_next/data/` لصفحات `getStaticProps`. هذه الطلبات ستتم دائمًا ضد النطاق الرئيسي لدعم [التوليد الثابت التدريجي (Incremental Static Generation)](/docs/pages/guides/incremental-static-regeneration)، حتى إذا لم تكن تستخدمه (لضمان الاتساق). + + \ No newline at end of file diff --git a/apps/docs/content/ar/docs/01-app/03-api-reference/05-config/01-next-config-js/authInterrupts.mdx b/apps/docs/content/ar/docs/01-app/03-api-reference/05-config/01-next-config-js/authInterrupts.mdx new file mode 100644 index 00000000..f53ca19f --- /dev/null +++ b/apps/docs/content/ar/docs/01-app/03-api-reference/05-config/01-next-config-js/authInterrupts.mdx @@ -0,0 +1,35 @@ +--- +source-updated-at: 2025-08-09T22:43:46.028Z +translation-updated-at: 2025-08-09T22:43:46.028Z +title: authInterrupts +description: تعرف على كيفية تمكين خيار التكوين التجريبي `authInterrupts` لاستخدام `forbidden` و `unauthorized`. +version: canary +related: + links: + - app/api-reference/functions/forbidden + - app/api-reference/functions/unauthorized + - app/api-reference/file-conventions/forbidden + - app/api-reference/file-conventions/unauthorized +--- + +يتيح لك خيار التكوين `authInterrupts` استخدام واجهات برمجة التطبيقات [`forbidden`](/docs/app/api-reference/functions/forbidden) و [`unauthorized`](/docs/app/api-reference/functions/unauthorized) في تطبيقك. بينما تعتبر هذه الوظائف تجريبية، يجب عليك تمكين خيار `authInterrupts` في ملف `next.config.js` الخاص بك لاستخدامها: + +```ts filename="next.config.ts" switcher +import type { NextConfig } from 'next' + +const nextConfig: NextConfig = { + experimental: { + authInterrupts: true, + }, +} + +export default nextConfig +``` + +```js filename="next.config.js" switcher +module.exports = { + experimental: { + authInterrupts: true, + }, +} +``` \ No newline at end of file diff --git a/apps/docs/content/ar/docs/01-app/03-api-reference/05-config/01-next-config-js/basePath.mdx b/apps/docs/content/ar/docs/01-app/03-api-reference/05-config/01-next-config-js/basePath.mdx new file mode 100644 index 00000000..916cb07c --- /dev/null +++ b/apps/docs/content/ar/docs/01-app/03-api-reference/05-config/01-next-config-js/basePath.mdx @@ -0,0 +1,81 @@ +--- +source-updated-at: 2025-08-09T22:43:46.028Z +translation-updated-at: 2025-08-09T22:43:46.028Z +title: basePath +description: استخدم `basePath` لنشر تطبيق Next.js تحت مسار فرعي ضمن نطاق. +--- + +{/* يتم مشاركة محتوى هذه الوثيقة بين موجه التطبيق وموجه الصفحات. يمكنك استخدام المكون `المحتوى` لإضافة محتوى محدد لموجه الصفحات. أي محتوى مشترك يجب عدم تضمينه في مكون. */} + +لنشر تطبيق Next.js تحت مسار فرعي ضمن نطاق، يمكنك استخدام خيار التكوين `basePath`. + +يسمح لك `basePath` بتعيين بادئة مسار للتطبيق. على سبيل المثال، لاستخدام `/docs` بدلاً من `''` (سلسلة فارغة، القيمة الافتراضية)، افتح ملف `next.config.js` وأضف تكوين `basePath`: + +```js filename="next.config.js" +module.exports = { + basePath: '/docs', +} +``` + +> **معلومة مفيدة**: يجب تعيين هذه القيمة أثناء وقت البناء ولا يمكن تغييرها دون إعادة البناء لأن القيمة مضمنة في حزم جانب العميل. + +### الروابط + +عند الربط بصفحات أخرى باستخدام `next/link` و `next/router`، سيتم تطبيق `basePath` تلقائيًا. + +على سبيل المثال، استخدام `/about` سيصبح تلقائيًا `/docs/about` عندما يتم تعيين `basePath` إلى `/docs`. + +```js +export default function HomePage() { + return ( + <> + صفحة حول + + ) +} +``` + +إخراج HTML: + +```html +صفحة حول +``` + +هذا يضمن أنك لست بحاجة لتغيير جميع الروابط في تطبيقك عند تغيير قيمة `basePath`. + +### الصور + + + +عند استخدام مكون [`next/image`](/docs/app/api-reference/components/image)، ستحتاج إلى إضافة `basePath` قبل `src`. + + + + + +عند استخدام مكون [`next/image`](/docs/pages/api-reference/components/image)، ستحتاج إلى إضافة `basePath` قبل `src`. + + + +على سبيل المثال، استخدام `/docs/me.png` سيخدم صورتك بشكل صحيح عندما يتم تعيين `basePath` إلى `/docs`. + +```jsx +import Image from 'next/image' + +function Home() { + return ( + <> +

صفحتي الرئيسية

+ صورة المؤلف +

مرحبًا بكم في صفحتي الرئيسية!

+ + ) +} + +export default Home +``` \ No newline at end of file diff --git a/apps/docs/content/ar/docs/01-app/05-api-reference/05-config/01-next-config-js/dynamicIO.mdx b/apps/docs/content/ar/docs/01-app/03-api-reference/05-config/01-next-config-js/cacheComponents.mdx similarity index 100% rename from apps/docs/content/ar/docs/01-app/05-api-reference/05-config/01-next-config-js/dynamicIO.mdx rename to apps/docs/content/ar/docs/01-app/03-api-reference/05-config/01-next-config-js/cacheComponents.mdx diff --git a/apps/docs/content/ar/docs/01-app/05-api-reference/05-config/01-next-config-js/cacheLife.mdx b/apps/docs/content/ar/docs/01-app/03-api-reference/05-config/01-next-config-js/cacheLife.mdx similarity index 100% rename from apps/docs/content/ar/docs/01-app/05-api-reference/05-config/01-next-config-js/cacheLife.mdx rename to apps/docs/content/ar/docs/01-app/03-api-reference/05-config/01-next-config-js/cacheLife.mdx diff --git a/apps/docs/content/ar/docs/01-app/03-api-reference/05-config/01-next-config-js/compress.mdx b/apps/docs/content/ar/docs/01-app/03-api-reference/05-config/01-next-config-js/compress.mdx new file mode 100644 index 00000000..4db3260e --- /dev/null +++ b/apps/docs/content/ar/docs/01-app/03-api-reference/05-config/01-next-config-js/compress.mdx @@ -0,0 +1,24 @@ +--- +source-updated-at: 2025-08-09T22:43:46.028Z +translation-updated-at: 2025-08-09T22:43:46.028Z +title: ضغط الملفات (compress) +description: يوفر Next.js ضغطًا باستخدام gzip لضغط المحتوى المُصيَّر والملفات الثابتة، وهو يعمل فقط مع هدف الخادم. تعرّف على المزيد حول ذلك هنا. +--- + +{/* يتم مشاركة محتوى هذا المستند بين موجه التطبيق (app router) وموجه الصفحات (pages router). يمكنك استخدام مكون `المحتوى` لإضافة محتوى خاص بموجه الصفحات. أي محتوى مشترك لا يجب أن يكون مغلفًا داخل مكون. */} + +بشكل افتراضي، يستخدم Next.js `gzip` لضغط المحتوى المُصيَّر والملفات الثابتة عند استخدام `next start` أو خادم مخصص. هذه تحسين للتطبيقات التي لا تحتوي على ضغط مُهيأ. إذا كان الضغط _مُهيأ بالفعل_ في تطبيقك عبر خادم مخصص، فلن يقوم Next.js بإضافة الضغط. + +يمكنك التحقق مما إذا كان الضغط مفعلًا وأي خوارزمية مستخدمة من خلال النظر إلى رؤوس [`Accept-Encoding`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept-Encoding) (الخيارات المقبولة من المتصفح) و [`Content-Encoding`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Encoding) (المستخدمة حاليًا) في الاستجابة. + +## تعطيل الضغط + +لتعطيل **الضغط**، عيّن خيار التكوين `compress` إلى `false`: + +```js filename="next.config.js" +module.exports = { + compress: false, +} +``` + +**لا نوصي بتعطيل الضغط** إلا إذا كان لديك ضغط مُهيأ على خادمك، حيث أن الضغط يقلل من استخدام النطاق الترددي ويحسن أداء تطبيقك. على سبيل المثال، إذا كنت تستخدم [nginx](https://nginx.org/) وتريد التبديل إلى `brotli`، فعيّن خيار `compress` إلى `false` للسماح لـ nginx بالتعامل مع الضغط. \ No newline at end of file diff --git a/apps/docs/content/ar/docs/01-app/03-api-reference/05-config/01-next-config-js/crossOrigin.mdx b/apps/docs/content/ar/docs/01-app/03-api-reference/05-config/01-next-config-js/crossOrigin.mdx new file mode 100644 index 00000000..4f3ac2c8 --- /dev/null +++ b/apps/docs/content/ar/docs/01-app/03-api-reference/05-config/01-next-config-js/crossOrigin.mdx @@ -0,0 +1,21 @@ +--- +source-updated-at: 2025-08-09T22:43:46.028Z +translation-updated-at: 2025-08-09T22:43:46.028Z +title: crossOrigin +description: استخدم خيار `crossOrigin` لإضافة سمة crossOrigin في علامات `script` التي يتم إنشاؤها بواسطة `next/script`. +--- + +{/* محتوى هذا المستند مشترك بين موجه التطبيق وموجه الصفحات. يمكنك استخدام مكون `المحتوى` لإضافة محتوى خاص بموجه الصفحات. أي محتوى مشترك لا يجب أن يكون مغلفًا بمكون. */} + +استخدم خيار `crossOrigin` لإضافة [سمة `crossOrigin`](https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/crossorigin) في جميع علامات ` diff --git a/apps/docs/content/en/learn/01-react-foundations/05-building-ui-with-components.mdx b/apps/docs/content/en/learn/01-react-foundations/05-building-ui-with-components.mdx index 745b44cd..08da3594 100644 --- a/apps/docs/content/en/learn/01-react-foundations/05-building-ui-with-components.mdx +++ b/apps/docs/content/en/learn/01-react-foundations/05-building-ui-with-components.mdx @@ -42,10 +42,9 @@ In React, components are **functions.** Inside your `script` tag, create a new f ```html {4,5} filename="index.html" ``` -与您在上一节中编写的 **命令式** JavaScript 代码: +与您在前一节中编写的命令式 JavaScript 代码: ```html filename="index.html" ``` -您可以开始看到使用 React 如何帮助您减少大量重复代码。 +您可以开始体会到使用 React 如何帮助减少大量重复代码。 -这正是 React 的作用,它是一个包含可重用代码片段的库,可以代表您执行任务——在本例中是更新 UI。 +这正是 React 的作用——它是一个包含可复用代码片段的库,这些代码片段可代您执行任务(在本例中是更新 UI)。 -> **额外资源:** +> **补充资源:** > -> 您不需要确切了解 React 如何更新 UI 即可开始使用它,但如果您想了解更多,以下是一些额外资源: +> 您无需确切了解 React 如何更新 UI 即可开始使用它,但如果您想了解更多,请参考以下资源: > > * [UI 树](https://react.dev/learn/understanding-your-ui-as-a-tree) > * [使用 JSX 编写标记](https://react.dev/learn/writing-markup-with-jsx) -> * [react-dom/server](https://react.dev/reference/react-dom/server) 部分在 React 文档中。 +> * React 文档中的 [react-dom/server](https://react.dev/reference/react-dom/server) 部分 [React 必备的 JavaScript 知识](#essential-javascript-for-react) ----------------------------------------------------------------- 虽然您可以同时学习 JavaScript 和 React,但熟悉 JavaScript 可以使学习 React 的过程更加轻松。 -在接下来的部分中,您将从 JavaScript 的角度了解 React 的一些核心概念。以下是将会提到的 JavaScript 主题摘要: +在接下来的章节中,您将从 JavaScript 角度了解 React 的一些核心概念。以下是将会提及的 JavaScript 主题摘要: * [函数](https://developer.mozilla.org/docs/Web/JavaScript/Guide/Functions) 和 [箭头函数](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Functions/Arrow_functions) * [对象](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) @@ -145,4 +146,5 @@ JSX 是 JavaScript 的一种语法扩展,允许您以熟悉的 _类 HTML_ 语 * [三元运算符](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Operators/Conditional_Operator) * [ES 模块和导入/导出语法](https://developer.mozilla.org/docs/Web/JavaScript/Guide/Modules) -虽然本课程不会深入探讨 JavaScript,但保持对最新 JavaScript 版本的了解是一个好习惯。但如果您对 JavaScript 还不熟练,请不要让这阻碍您开始使用 React 进行构建! \ No newline at end of file +虽然本课程不深入讲解 JavaScript,但保持了解最新版本的 JavaScript 是良好的实践。不过,如果您对 JavaScript 还不熟练,也不要因此阻碍您开始使用 React 进行构建! +``` \ No newline at end of file diff --git a/apps/docs/content/zh-hans/learn/01-react-foundations/05-building-ui-with-components.mdx b/apps/docs/content/zh-hans/learn/01-react-foundations/05-building-ui-with-components.mdx index 0e59de01..eabe186c 100644 --- a/apps/docs/content/zh-hans/learn/01-react-foundations/05-building-ui-with-components.mdx +++ b/apps/docs/content/zh-hans/learn/01-react-foundations/05-building-ui-with-components.mdx @@ -1,8 +1,8 @@ --- -source-updated-at: 2025-05-29T19:07:21.000Z -translation-updated-at: 2025-05-29T19:50:29.891Z +source-updated-at: 2025-08-09T22:43:53.000Z +translation-updated-at: 2025-08-09T23:01:03.923Z title: 使用组件构建用户界面 -headline: 'React 基础:使用组件构建用户界面' +headline: React 基础 - 使用组件构建用户界面 description: 学习如何使用 React 组件构建可组合的用户界面。 image: >- https://nextjs.org/api/learn-og?title=Building%20UI%20with%20Components&chapter=5 @@ -11,80 +11,79 @@ image: >- [React 核心概念](#react-core-concepts) ------------------------------------------- -开始构建 React 应用前,您需要熟悉以下三个核心概念: +开始构建 React 应用需要熟悉三个核心概念: -* 组件 (Components) +* 组件 (Component) * 属性 (Props) * 状态 (State) -在接下来的章节中,我们将逐一介绍这些概念,并提供继续学习的资源。熟悉这些概念后,我们将展示如何安装 Next.js 并使用服务端组件 (Server Components) 和客户端组件 (Client Components) 等新特性。 +在后续章节中,我们将探讨这些概念并提供学习资源。熟悉这些概念后,我们将介绍如何安装 Next.js 并使用服务端组件 (Server Components) 和客户端组件 (Client Components) 等新特性。 [组件](#components) ------------------------- -用户界面可以拆分为更小的构建块,称为**组件**。 +用户界面可以拆分为称为**组件**的较小构建块。 -组件允许您构建自包含、可复用的代码片段。如果将组件视为**乐高积木**,您可以将这些独立积木组合起来形成更大的结构。当需要更新部分用户界面时,只需更新特定的组件或"积木"即可。 +组件允许您构建自包含、可复用的代码片段。若将组件视为**乐高积木**,您可以将这些独立积木组合成更大结构。当需要更新部分 UI 时,只需更新特定组件或积木。 媒体组件示例,由图像、文本和按钮三个小组件构成 -这种模块化设计使您的代码在增长时更易于维护,因为您可以添加、更新和删除组件而无需改动应用的其他部分。 +这种模块化设计让代码在增长过程中更易维护,因为您可以添加、更新或删除组件而不影响应用其他部分。 -React 组件的优势在于它们本质上就是 JavaScript。让我们从 JavaScript 角度看看如何编写 React 组件: +React 组件的优势在于它们本质上是 JavaScript。让我们从 JavaScript 角度了解如何编写 React 组件: ### [创建组件](#creating-components) -在 React 中,组件就是**函数**。在 `script` 标签内创建一个名为 `header` 的新函数: +在 React 中,组件即**函数**。在 `script` 标签内创建名为 `header` 的函数: ```html {4,5} filename="index.html" ``` -组件是返回 UI 元素的函数。在函数的 return 语句中,您可以编写 JSX: +组件是**返回 UI 元素**的函数。在函数的 return 语句中编写 JSX: ```html {5} filename="index.html" ``` -要将此组件渲染到 DOM,将其作为第一个参数传递给 `root.render()` 方法: +要将此组件渲染到 DOM,将其作为首个参数传入 `root.render()` 方法: ```html {9} filename="index.html" ``` -但请注意,如果直接在浏览器中运行上述代码会出现错误。要使代码正常工作,需要做两件事: +但请注意:在浏览器中运行上述代码会报错。需进行两项修正: 首先,React 组件名称应大写以区别于普通 HTML 和 JavaScript: @@ -98,7 +97,7 @@ const root = ReactDOM.createRoot(app); root.render(Header); ``` -其次,使用 React 组件的方式与常规 HTML 标签相同,需要使用尖括号 `<>`: +其次,使用 React 组件的方式与常规 HTML 标签相同,需使用尖括号 `<>`: ```html {6} filename="index.html" function Header() { @@ -109,13 +108,13 @@ const root = ReactDOM.createRoot(app); root.render(
); ``` -再次在浏览器中运行代码,即可看到效果。 +再次在浏览器中运行代码即可看到效果。 ### [嵌套组件](#nesting-components) -应用通常包含比单个组件更多的内容。您可以像嵌套 HTML 元素一样**嵌套** React 组件。 +应用通常包含多个组件。您可以像嵌套 HTML 元素那样**嵌套** React 组件。 -在示例中创建一个名为 `HomePage` 的新组件: +创建名为 `HomePage` 的新组件: ```html {5,6,7} filename="index.html" function Header() { @@ -130,7 +129,7 @@ const root = ReactDOM.createRoot(app); root.render(
); ``` -然后将 `
` 组件嵌套到新的 `` 组件中: +将 `
` 组件嵌套在新组件 `` 中: ```html {7,8,9,10} filename="index.html" function Header() { @@ -152,21 +151,21 @@ root.render(
); ### [组件树](#component-trees) -通过这种方式不断嵌套 React 组件,可以形成组件树。 +通过这种方式持续嵌套 React 组件,可形成组件树。 展示组件如何相互嵌套的组件树示意图 -例如,顶级 `HomePage` 组件可以包含 `Header`、`Article` 和 `Footer` 组件。而这些组件又可以有自己的子组件,依此类推。比如 `Header` 组件可能包含 `Logo`、`Title` 和 `Navigation` 组件。 +例如,顶层 `HomePage` 组件可包含 `Header`、`Article` 和 `Footer` 组件。这些组件又可拥有各自的子组件(如 `Header` 可包含 `Logo`、`Title` 和 `Navigation` 组件)。 -这种模块化格式允许您在应用的不同位置复用组件。 +这种模块化格式支持在应用不同位置复用组件。 -在项目中,由于 `` 现在是顶级组件,可以将其传递给 `root.render()` 方法: +在项目中,由于 `` 现为顶层组件,可将其传入 `root.render()` 方法: ```html {14} filename="index.html" function Header() { @@ -185,7 +184,7 @@ const root = ReactDOM.createRoot(app); root.render(); ``` -> **延伸阅读:** +> **扩展资源:** > -> * [第一个组件](https://react.dev/learn/your-first-component) -> * [导入和导出组件](https://react.dev/learn/importing-and-exporting-components) \ No newline at end of file +> * [创建第一个组件](https://react.dev/learn/your-first-component) +> * [组件的导入与导出](https://react.dev/learn/importing-and-exporting-components) \ No newline at end of file diff --git a/apps/docs/content/zh-hans/learn/02-dashboard-app/06-setting-up-your-database.mdx b/apps/docs/content/zh-hans/learn/02-dashboard-app/06-setting-up-your-database.mdx index cf911e7d..6424435b 100644 --- a/apps/docs/content/zh-hans/learn/02-dashboard-app/06-setting-up-your-database.mdx +++ b/apps/docs/content/zh-hans/learn/02-dashboard-app/06-setting-up-your-database.mdx @@ -1,49 +1,50 @@ +``` --- -source-updated-at: 2025-05-29T18:05:49.000Z -translation-updated-at: 2025-05-29T19:49:02.879Z -title: 数据库设置指南 -headline: '应用路由 (App Router): 数据库设置指南' -description: 为您的应用程序设置数据库并填充初始数据。 +source-updated-at: 2025-08-09T22:43:53.000Z +translation-updated-at: 2025-08-09T23:01:49.599Z +title: 设置数据库 +headline: 应用路由器 - 数据库设置 +description: 为您的应用程序配置数据库并用初始数据填充。 image: >- https://nextjs.org/api/learn-og?title=Setting%20Up%20Your%20Database&chapter=6 --- -在继续开发仪表盘之前,您需要准备一些数据。本章将指导您通过 [Vercel 市场集成](https://vercel.com/marketplace?category=databases) 设置 PostgreSQL 数据库。如果您已熟悉 PostgreSQL 并希望使用自己的数据库提供商,可以跳过本章自行设置。否则,让我们继续吧! +在继续开发仪表盘之前,您需要准备一些数据。本章将指导您通过 [Vercel 市场集成](https://vercel.com/marketplace?category=storage) 设置 PostgreSQL 数据库。如果您已熟悉 PostgreSQL 并希望使用自己的数据库提供商,可跳过本章自行配置。否则,让我们开始吧! [创建 GitHub 仓库](#create-a-github-repository) --------------------------------------------------------- -首先,如果您尚未操作,请将代码库推送至 GitHub。这将简化数据库设置和部署流程。 +首先,请将您的代码库推送至 GitHub(如果尚未操作)。这将简化数据库设置和部署流程。 -如需仓库设置帮助,请参考 [GitHub 官方指南](https://help.github.com/en/github/getting-started-with-github/create-a-repo)。 +如需仓库设置帮助,请参阅 [GitHub 官方指南](https://help.github.com/en/github/getting-started-with-github/create-a-repo)。 > **须知:** > -> * 您也可以使用其他 Git 服务如 GitLab 或 Bitbucket -> * 若您是 GitHub 新手,推荐使用 [GitHub 桌面客户端](https://desktop.github.com/) 简化开发流程 +> * 您也可以使用 GitLab 或 Bitbucket 等其他 git 服务 +> * 若初次接触 GitHub,推荐使用 [GitHub 桌面应用](https://desktop.github.com/) 简化开发流程 [创建 Vercel 账户](#create-a-vercel-account) --------------------------------------------------- -访问 [vercel.com/signup](https://vercel.com/signup) 注册账户。选择免费的 "hobby" 套餐,点击 **Continue with GitHub** 关联您的 GitHub 和 Vercel 账户。 +访问 [vercel.com/signup](https://vercel.com/signup) 创建账户。选择免费的 "hobby" 计划,点击 **Continue with GitHub** 连接您的 GitHub 和 Vercel 账户。 [连接并部署项目](#connect-and-deploy-your-project) ------------------------------------------------------------------- -接下来您将看到以下界面,选择并 **导入** 您刚创建的 GitHub 仓库: +接下来您将进入此界面,选择并 **导入** 您创建的 GitHub 仓库: Vercel 仪表盘截图:显示导入项目界面及用户的 GitHub 仓库列表 -输入项目名称后点击 **部署**。 +输入项目名称并点击 **Deploy**。 部署界面:显示项目名称输入框和部署按钮- 恭喜!🎉 您的项目已成功部署。 项目概览界面:显示项目名称、域名和部署状态 -关联 GitHub 仓库后,每当您向 **main** 分支推送更改时,Vercel 将自动重新部署应用而无需额外配置。提交拉取请求时,您还会获得 [即时预览链接](https://vercel.com/docs/deployments/environments#preview-environment-pre-production#preview-urls),便于及早发现部署问题并与团队成员分享项目预览以获取反馈。 +连接 GitHub 仓库后,每当您向 **main** 分支推送更改时,Vercel 将自动重新部署应用,无需额外配置。提交拉取请求时,您还会获得 [即时预览链接](https://vercel.com/docs/deployments/environments#preview-environment-pre-production#preview-urls),便于及早发现部署错误并与团队成员共享项目预览。 [创建 PostgreSQL 数据库](#create-a-postgres-database) --------------------------------------------------------- -接下来点击 **Continue to Dashboard**,在项目仪表盘中选择 **Storage** 标签页,点击 **Create Database**。根据您的 Vercel 账户创建时间,您可能看到 Neon 或 Supabase 等选项。选择首选提供商后点击 **Continue**。 +接下来点击 **Continue to Dashboard**,在项目仪表盘的 **Storage** 标签页选择 **Create Database**。根据您的 Vercel 账户创建时间,可能会看到 Neon 或 Supabase 等选项。选择首选供应商并点击 **Continue**。 数据库连接界面:显示 PostgreSQL 选项及 KV、Blob 和 Edge Config 等其他存储选项 -选择区域和存储方案(如需要)。所有 Vercel 项目的 [默认区域](https://vercel.com/docs/functions/configuring-functions/region) 是 **华盛顿特区 (iad1)**,为降低 [数据请求延迟](https://developer.mozilla.org/en-US/docs/Web/Performance/Understanding_latency),建议优先选择该区域。 +选择区域和存储计划(如需要)。所有 Vercel 项目的 [默认区域](https://vercel.com/docs/functions/configuring-functions/region) 是 **华盛顿特区 (iad1)**,建议选择此区域以减少数据请求的 [延迟](https://developer.mozilla.org/en-US/docs/Web/Performance/Understanding_latency)。 数据库创建弹窗:显示数据库名称和区域选择 -连接成功后,导航至 `.env.local` 标签页,点击 **Show secret** 并 **Copy Snippet**。请确保在复制前已显示所有密钥。 +连接成功后,导航至 `.env.local` 标签页,点击 **Show secret** 并 **复制代码片段**。请确保先显示密钥再复制。 .env.local 标签页:显示隐藏的数据库密钥 -返回代码编辑器,将 `.env.example` 文件重命名为 **`.env`**,并粘贴从 Vercel 复制的配置内容。 +在代码编辑器中重命名 `.env.example` 文件为 **`.env`**,粘贴从 Vercel 复制的内容。 -> **重要提示:** 检查 `.gitignore` 文件,确保已忽略 `.env` 文件,防止推送至 GitHub 时泄露数据库密钥。 +> **重要提示:** 检查 `.gitignore` 文件,确保 `.env` 在忽略列表中,防止推送至 GitHub 时泄露数据库密钥。 -[数据库初始化](#seed-your-database) +[填充数据库](#seed-your-database) ----------------------------------------- -数据库创建完成后,让我们填充初始数据。 +数据库创建完成后,让我们用初始数据填充它。 + +我们提供了可通过浏览器访问的 API,该 API 将运行种子脚本,用初始数据集填充数据库。 -我们已内置一个可通过浏览器访问的 API 端点,该端点将运行初始化脚本为数据库填充预设数据。脚本使用 **SQL** 创建数据表,并通过 `placeholder-data.ts` 文件中的数据完成填充。 +该脚本使用 **SQL** 创建数据表,并利用 `placeholder-data.ts` 文件的数据在创建后填充它们。 -确保本地开发服务器正在运行(执行 `pnpm run dev`),然后在浏览器中访问 [`localhost:3000/seed`](http://localhost:3000/seed)。完成后浏览器将显示 "Database seeded successfully" 提示信息。初始化完成后可删除此文件。 +确保本地开发服务器通过 `pnpm run dev` 运行,并在浏览器中访问 [`localhost:3000/seed`](http://localhost:3000/seed)。完成后浏览器将显示 "Database seeded successfully" 信息。操作完成后可删除此文件。 > **故障排除:** > -> * 请确认在复制到 `.env` 文件前已显示所有数据库密钥 -> * 脚本使用 `bcrypt` 哈希用户密码,若环境不兼容可改用 [`bcryptjs`](https://www.npmjs.com/package/bcryptjs) -> * 若初始化遇到问题需重新运行脚本,可在数据库查询界面执行 `DROP TABLE tablename` 删除现有表(详见下方 [执行查询](#executing-queries) 部分)。注意:此命令将永久删除表及其所有数据。示例应用中使用占位数据可执行此操作,但切勿在生产环境中使用。 +> * 请确保在将数据库密钥复制到 `.env` 文件前已显示密钥 +> * 脚本使用 `bcrypt` 哈希用户密码,若 `bcrypt` 与您的环境不兼容,可改用 [`bcryptjs`](https://www.npmjs.com/package/bcryptjs) +> * 若填充数据库时遇到问题需重新运行脚本,可在数据库查询界面执行 `DROP TABLE tablename` 删除现有表(详见下方 [执行查询](#executing-queries) 部分)。注意:此命令将删除表及其所有数据。示例应用中使用占位数据可执行此操作,但生产环境中切勿运行 [执行查询](#executing-queries) --------------------------------------- -让我们执行查询验证功能是否正常。我们将使用另一个路由处理器 `app/query/route.ts` 来查询数据库。该文件包含的 `listInvoices()` 函数有如下 SQL 查询: +让我们执行查询以验证一切正常运行。我们将使用另一个路由处理器 `app/query/route.ts` 查询数据库。该文件中的 `listInvoices()` 函数包含以下 SQL 查询: ``` SELECT invoices.amount, customers.name @@ -126,4 +129,5 @@ JOIN customers ON invoices.customer_id = customers.id WHERE invoices.amount = 666; ``` -取消文件注释,移除 `Response.json() 代码块`,然后在浏览器中访问 [`localhost:3000/query`](http://localhost:3000/query)。您将看到返回的发票 `amount` 和客户 `name` 数据。 \ No newline at end of file +取消文件注释,移除 `Response.json() 代码块`,在浏览器中访问 [`localhost:3000/query`](http://localhost:3000/query)。您将看到返回的发票 `amount` 和 `name` 数据。 +``` \ No newline at end of file diff --git a/apps/docs/content/zh-hans/learn/02-dashboard-app/16-adding-metadata.mdx b/apps/docs/content/zh-hans/learn/02-dashboard-app/16-adding-metadata.mdx index 0868a50b..82ee06f5 100644 --- a/apps/docs/content/zh-hans/learn/02-dashboard-app/16-adding-metadata.mdx +++ b/apps/docs/content/zh-hans/learn/02-dashboard-app/16-adding-metadata.mdx @@ -1,101 +1,99 @@ --- -source-updated-at: 2025-05-29T18:05:49.000Z -translation-updated-at: 2025-05-29T19:47:56.493Z +source-updated-at: 2025-08-09T22:43:53.000Z +translation-updated-at: 2025-08-09T23:01:23.173Z title: 添加元数据 -headline: '应用路由 (App Router): 添加元数据' -description: 学习如何为 Next.js 应用添加元数据。 -image: 'https://nextjs.org/api/learn-og?title=Adding%20Metadata&chapter=16' +headline: 应用路由器中的元数据添加 +description: 学习如何为 Next.js 应用程序添加元数据。 +image: https://nextjs.org/api/learn-og?title=Adding%20Metadata&chapter=16 --- -元数据对于 SEO 和内容分享至关重要。本章将介绍如何为 Next.js 应用添加元数据。 +元数据对于 SEO(搜索引擎优化)和可分享性至关重要。在本章中,我们将讨论如何为 Next.js 应用程序添加元数据。 [什么是元数据?](#what-is-metadata) -------------------------------------- -在网页开发中,元数据提供了关于网页的额外信息。这些信息对访问用户不可见,而是嵌入在页面的 HTML `` 元素中,在后台发挥作用。这些隐藏信息对于搜索引擎和其他需要理解网页内容的系统非常重要。 +在 Web 开发中,元数据提供了关于网页的额外详细信息。访问页面的用户不会直接看到元数据。它通常嵌入在页面的 HTML 中(主要在 `` 元素内),在后台发挥作用。这些隐藏信息对搜索引擎和其他需要理解网页内容的系统至关重要。 [为什么元数据很重要?](#why-is-metadata-important) -------------------------------------------------------- -元数据在提升网页 SEO 方面起着重要作用,使搜索引擎和社交媒体平台更容易理解和访问网页内容。恰当的元数据能帮助搜索引擎有效索引网页,提高其在搜索结果中的排名。此外,像开放图谱 (Open Graph) 这样的元数据可以优化链接在社交媒体上的展示效果,使内容更具吸引力和信息性。 +元数据在提升网页 SEO 方面起着重要作用,使搜索引擎和社交媒体平台更容易理解和访问网页。正确的元数据帮助搜索引擎有效索引网页,提高其在搜索结果中的排名。此外,Open Graph 等元数据能优化社交媒体上分享链接的显示效果,使内容更具吸引力和信息量。 [元数据类型](#types-of-metadata) --------------------------------------- -元数据有多种类型,每种都有其独特用途。常见类型包括: +元数据有各种类型,每种都有独特用途。常见类型包括: -**标题元数据 (Title Metadata)**: 决定显示在浏览器标签页上的网页标题,对 SEO 至关重要,帮助搜索引擎理解网页内容。 +**标题元数据**:决定显示在浏览器标签页上的网页标题,对 SEO 至关重要,帮助搜索引擎理解网页内容。 ``` -页面标题 +Page Title ``` -**描述元数据 (Description Metadata)**: 提供网页内容的简要概述,通常显示在搜索引擎结果中。 +**描述元数据**:提供网页内容的简要概述,通常显示在搜索引擎结果中。 ``` - + ``` -**关键词元数据 (Keyword Metadata)**: 包含与网页内容相关的关键词,帮助搜索引擎索引页面。 +**关键词元数据**:包含与网页内容相关的关键词,帮助搜索引擎索引页面。 ``` - + ``` -**开放图谱元数据 (Open Graph Metadata)**: 增强网页在社交媒体平台上的展示效果,提供标题、描述和预览图等信息。 +**Open Graph 元数据**:增强网页在社交媒体平台分享时的展示效果,提供标题、描述和预览图等信息。 ``` - - - + + + ``` -**网站图标元数据 (Favicon Metadata)**: 关联网站图标 (favicon),显示在浏览器地址栏或标签页上。 +**网站图标元数据**:将 favicon(小图标)链接到网页,显示在浏览器地址栏或标签页。 ``` - + ``` [添加元数据](#adding-metadata) ----------------------------------- -Next.js 提供了元数据 API 来定义应用元数据。有两种方式可以为应用添加元数据: +Next.js 提供了 Metadata API 用于定义应用程序元数据。有两种添加元数据的方式: -* **基于配置**: 在 `layout.js` 或 `page.js` 文件中导出[静态 `metadata` 对象](/docs/app/api-reference/functions/generate-metadata#metadata-object)或动态的 [`generateMetadata` 函数](/docs/app/api-reference/functions/generate-metadata#generatemetadata-function)。 - -* **基于文件**: Next.js 提供了一系列专门用于元数据的特殊文件: - - * `favicon.ico`、`apple-icon.jpg` 和 `icon.jpg`: 用于网站图标 - * `opengraph-image.jpg` 和 `twitter-image.jpg`: 用于社交媒体图片 - * `robots.txt`: 提供搜索引擎爬取指令 - * `sitemap.xml`: 提供网站结构信息 +* **基于配置**:在 `layout.js` 或 `page.js` 文件中导出[静态 `metadata` 对象](/docs/app/api-reference/functions/generate-metadata#metadata-object)或动态 [`generateMetadata` 函数](/docs/app/api-reference/functions/generate-metadata#generatemetadata-function) +* **基于文件**:Next.js 提供了一系列专门用于元数据的特殊文件: + * `favicon.ico`、`apple-icon.jpg` 和 `icon.jpg`:用于网站图标 + * `opengraph-image.jpg` 和 `twitter-image.jpg`:用于社交媒体图片 + * `robots.txt`:提供搜索引擎爬取指令 + * `sitemap.xml`:提供网站结构信息 -你可以灵活选择使用这些文件作为静态元数据,也可以在项目中以编程方式生成它们。 +您可以使用这些文件处理静态元数据,也可以在项目中动态生成它们。 -使用这两种方式,Next.js 都会自动为页面生成相应的 `` 元素。 +通过这两种方式,Next.js 都会自动为页面生成相应的 `` 元素。 -### [网站图标和开放图谱图片](#favicon-and-open-graph-image) +### [网站图标和 Open Graph 图片](#favicon-and-open-graph-image) -在 `/public` 文件夹中,你会看到两个图片文件:`favicon.ico` 和 `opengraph-image.jpg`。 +在您的 `/public` 文件夹中,您会看到两张图片:`favicon.ico` 和 `opengraph-image.jpg`。 将这些图片移动到 `/app` 文件夹的根目录。 -完成后,Next.js 会自动识别并使用这些文件作为网站图标和开放图谱图片。你可以通过开发者工具检查应用的 `` 元素来验证这一点。 +完成后,Next.js 会自动识别并使用这些文件作为网站图标和 OG 图片。您可以通过开发者工具检查应用程序的 `` 元素来验证。 -> **小提示**: 你还可以使用 [`ImageResponse`](/docs/app/api-reference/functions/image-response) 构造函数创建动态开放图谱图片。 +> **须知:** 您还可以使用 [`ImageResponse`](/docs/app/api-reference/functions/image-response) 构造函数创建动态 OG 图片。 ### [页面标题和描述](#page-title-and-descriptions) -你也可以在任何 `layout.js` 或 `page.js` 文件中包含 [`metadata` 对象](/docs/app/api-reference/functions/generate-metadata#metadata-fields)来添加页面信息,如标题和描述。`layout.js` 中的元数据会被所有使用它的页面继承。 +您可以在任何 `layout.js` 或 `page.js` 文件中添加 [`metadata` 对象](/docs/app/api-reference/functions/generate-metadata#metadata-fields)来补充页面信息(如标题和描述)。`layout.js` 中的元数据会被所有使用该布局的页面继承。 -在根布局中,创建一个包含以下字段的 `metadata` 对象: +在根布局中创建包含以下字段的 `metadata` 对象: ```tsx {1,3,4,5,6,7} filename="/app/layout.tsx" import { Metadata } from 'next'; export const metadata: Metadata = { - title: 'Acme 仪表盘', - description: '使用应用路由 (App Router) 构建的 Next.js 官方课程仪表盘', + title: 'Acme Dashboard', + description: '基于应用路由器构建的官方 Next.js 课程仪表盘', metadataBase: new URL('https://next-learn-dashboard.vercel.sh'), }; @@ -104,11 +102,11 @@ export default function RootLayout() { } ``` -Next.js 会自动将这些标题和元数据添加到你的应用中。 +Next.js 会自动将标题和元数据添加到应用程序中。 -如果想为特定页面添加自定义标题怎么办?你可以通过在该页面中添加 `metadata` 对象来实现。嵌套页面中的元数据会覆盖父级元数据。 +如果需要对特定页面设置自定义标题怎么办?您可以在页面文件中添加 `metadata` 对象。嵌套页面的元数据会覆盖父级元数据。 -例如,在 `/dashboard/invoices` 页面中更新标题: +例如,在 `/dashboard/invoices` 页面更新标题: ```tsx {1,3,4,5} filename="/app/dashboard/invoices/page.tsx" import { Metadata } from 'next'; @@ -118,11 +116,11 @@ export const metadata: Metadata = { }; ``` -这种方式可行,但我们在每个页面都重复了应用标题。如果公司名称等发生变化,就需要在每个页面进行更新。 +这种方式可行,但我们在每个页面重复了应用标题。如果公司名称变更,就需要在所有页面更新。 -相反,你可以在 `metadata` 对象中使用 `title.template` 字段定义页面标题模板。这个模板可以包含页面标题和其他你想包含的信息。 +您可以在 `metadata` 对象中使用 `title.template` 字段定义页面标题模板。该模板可包含页面标题和其他信息。 -在根布局中,更新 `metadata` 对象以包含模板: +在根布局中更新 `metadata` 对象以包含模板: ```tsx {1,3,4,5,6,7,8,9,10} filename="/app/layout.tsx" import { Metadata } from 'next'; @@ -132,14 +130,14 @@ export const metadata: Metadata = { template: '%s | Acme 仪表盘', default: 'Acme 仪表盘', }, - description: '使用应用路由 (App Router) 构建的 Next.js 学习仪表盘', + description: '基于应用路由器构建的 Next.js 学习仪表盘', metadataBase: new URL('https://next-learn-dashboard.vercel.sh'), }; ``` -模板中的 `%s` 将被替换为特定页面标题。 +模板中的 `%s` 会被替换为具体页面标题。 -现在,在 `/dashboard/invoices` 页面中,只需添加页面标题: +现在在 `/dashboard/invoices` 页面添加标题: ```tsx filename="/app/dashboard/invoices/page.tsx" export const metadata: Metadata = { @@ -147,12 +145,12 @@ export const metadata: Metadata = { }; ``` -访问 `/dashboard/invoices` 页面并检查 `` 元素,你会看到页面标题现在是 `发票 | Acme 仪表盘`。 +访问 `/dashboard/invoices` 页面并检查 `` 元素,您会看到页面标题已变为 `发票 | Acme 仪表盘`。 [练习:添加元数据](#practice-adding-metadata) ------------------------------------------------------ -现在你已经了解了元数据,请为以下页面添加标题进行练习: +现在您已了解元数据,请为以下页面添加标题: 1. `/login` 页面 2. `/dashboard/` 页面 @@ -160,4 +158,4 @@ export const metadata: Metadata = { 4. `/dashboard/invoices/create` 页面 5. `/dashboard/invoices/[id]/edit` 页面 -Next.js 元数据 API 功能强大且灵活,让你能完全控制应用的元数据。这里我们展示了如何添加一些基本元数据,但你还可以添加更多字段,包括 `keywords`、`robots`、`canonical` 等。欢迎探索[文档](/docs/app/api-reference/functions/generate-metadata),为你的应用添加任何额外的元数据。 \ No newline at end of file +Next.js Metadata API 功能强大且灵活,让您完全掌控应用程序元数据。这里我们演示了基础元数据添加,您还可以添加 `keywords`、`robots`、`canonical` 等更多字段。请随时查阅[文档](/docs/app/api-reference/functions/generate-metadata),为应用程序添加所需的其他元数据。 \ No newline at end of file diff --git a/apps/docs/content/zh-hant/docs/01-app/01-getting-started/08-server-and-client-components.mdx b/apps/docs/content/zh-hant/docs/01-app/01-getting-started/05-server-and-client-components.mdx similarity index 100% rename from apps/docs/content/zh-hant/docs/01-app/01-getting-started/08-server-and-client-components.mdx rename to apps/docs/content/zh-hant/docs/01-app/01-getting-started/05-server-and-client-components.mdx diff --git a/apps/docs/content/zh-hant/docs/01-app/01-getting-started/13-partial-prerendering.mdx b/apps/docs/content/zh-hant/docs/01-app/01-getting-started/06-partial-prerendering.mdx similarity index 100% rename from apps/docs/content/zh-hant/docs/01-app/01-getting-started/13-partial-prerendering.mdx rename to apps/docs/content/zh-hant/docs/01-app/01-getting-started/06-partial-prerendering.mdx diff --git a/apps/docs/content/zh-hant/docs/01-app/01-getting-started/09-fetching-data.mdx b/apps/docs/content/zh-hant/docs/01-app/01-getting-started/07-fetching-data.mdx similarity index 100% rename from apps/docs/content/zh-hant/docs/01-app/01-getting-started/09-fetching-data.mdx rename to apps/docs/content/zh-hant/docs/01-app/01-getting-started/07-fetching-data.mdx diff --git a/apps/docs/content/zh-hant/docs/01-app/01-getting-started/11-updating-data.mdx b/apps/docs/content/zh-hant/docs/01-app/01-getting-started/08-updating-data.mdx similarity index 100% rename from apps/docs/content/zh-hant/docs/01-app/01-getting-started/11-updating-data.mdx rename to apps/docs/content/zh-hant/docs/01-app/01-getting-started/08-updating-data.mdx diff --git a/apps/docs/content/zh-hant/docs/01-app/01-getting-started/10-caching-and-revalidating.mdx b/apps/docs/content/zh-hant/docs/01-app/01-getting-started/09-caching-and-revalidating.mdx similarity index 100% rename from apps/docs/content/zh-hant/docs/01-app/01-getting-started/10-caching-and-revalidating.mdx rename to apps/docs/content/zh-hant/docs/01-app/01-getting-started/09-caching-and-revalidating.mdx diff --git a/apps/docs/content/zh-hant/docs/01-app/01-getting-started/12-error-handling.mdx b/apps/docs/content/zh-hant/docs/01-app/01-getting-started/10-error-handling.mdx similarity index 100% rename from apps/docs/content/zh-hant/docs/01-app/01-getting-started/12-error-handling.mdx rename to apps/docs/content/zh-hant/docs/01-app/01-getting-started/10-error-handling.mdx diff --git a/apps/docs/content/zh-hant/docs/01-app/01-getting-started/07-css.mdx b/apps/docs/content/zh-hant/docs/01-app/01-getting-started/11-css.mdx similarity index 100% rename from apps/docs/content/zh-hant/docs/01-app/01-getting-started/07-css.mdx rename to apps/docs/content/zh-hant/docs/01-app/01-getting-started/11-css.mdx diff --git a/apps/docs/content/zh-hant/docs/01-app/01-getting-started/05-images.mdx b/apps/docs/content/zh-hant/docs/01-app/01-getting-started/12-images.mdx similarity index 100% rename from apps/docs/content/zh-hant/docs/01-app/01-getting-started/05-images.mdx rename to apps/docs/content/zh-hant/docs/01-app/01-getting-started/12-images.mdx diff --git a/apps/docs/content/zh-hant/docs/01-app/01-getting-started/06-fonts.mdx b/apps/docs/content/zh-hant/docs/01-app/01-getting-started/13-fonts.mdx similarity index 100% rename from apps/docs/content/zh-hant/docs/01-app/01-getting-started/06-fonts.mdx rename to apps/docs/content/zh-hant/docs/01-app/01-getting-started/13-fonts.mdx diff --git a/apps/docs/content/zh-hant/docs/01-app/01-getting-started/15-deploying.mdx b/apps/docs/content/zh-hant/docs/01-app/01-getting-started/16-deploying.mdx similarity index 100% rename from apps/docs/content/zh-hant/docs/01-app/01-getting-started/15-deploying.mdx rename to apps/docs/content/zh-hant/docs/01-app/01-getting-started/16-deploying.mdx diff --git a/apps/docs/content/zh-hant/docs/01-app/01-getting-started/16-upgrading.mdx b/apps/docs/content/zh-hant/docs/01-app/01-getting-started/17-upgrading.mdx similarity index 100% rename from apps/docs/content/zh-hant/docs/01-app/01-getting-started/16-upgrading.mdx rename to apps/docs/content/zh-hant/docs/01-app/01-getting-started/17-upgrading.mdx diff --git a/apps/docs/content/zh-hant/docs/01-app/04-deep-dive/caching.mdx b/apps/docs/content/zh-hant/docs/01-app/02-guides/caching.mdx similarity index 100% rename from apps/docs/content/zh-hant/docs/01-app/04-deep-dive/caching.mdx rename to apps/docs/content/zh-hant/docs/01-app/02-guides/caching.mdx diff --git a/apps/docs/content/zh-hant/docs/01-app/02-guides/tailwind-css.mdx b/apps/docs/content/zh-hant/docs/01-app/02-guides/tailwind-css.mdx deleted file mode 100644 index 1993e491..00000000 --- a/apps/docs/content/zh-hant/docs/01-app/02-guides/tailwind-css.mdx +++ /dev/null @@ -1,163 +0,0 @@ ---- -source-updated-at: 2025-06-01T01:32:20.000Z -translation-updated-at: 2025-06-01T22:23:21.972Z -title: 如何在 Next.js 應用程式中安裝 Tailwind CSS -nav_title: Tailwind CSS -description: 使用 Tailwind CSS 來為您的 Next.js 應用程式添加樣式。 ---- - -{/* 此文件內容在應用程式路由和頁面路由之間共享。您可以使用 `內容` 元件來添加特定於頁面路由的內容。任何共享內容不應包裹在元件中。 */} - -[Tailwind CSS](https://tailwindcss.com/) 是一個優先使用工具類的 CSS 框架,與 Next.js 完全相容。本指南將帶您了解如何在 Next.js 應用程式中安裝 Tailwind CSS。 - -## 安裝 Tailwind - -安裝必要的 Tailwind CSS 套件: - -```bash filename="終端機" -npm install -D tailwindcss @tailwindcss/postcss postcss -``` - -> **小提示**:如果您使用 `create-next-app` CLI 建立專案,Next.js 會詢問您是否要安裝 Tailwind 並自動配置專案。 - -## 配置 Tailwind - -在專案根目錄建立 `postcss.config.mjs` 檔案,並將 `@tailwindcss/postcss` 插件添加到您的 PostCSS 配置中: - -```js filename="postcss.config.mjs" highlight={4} -/** @type {import('tailwindcss').Config} */ -export default { - plugins: { - '@tailwindcss/postcss': {}, - }, -} -``` - -從 [Tailwind v4](https://tailwindcss.com/blog/tailwindcss-v4) 開始,預設不需要任何配置。如果您確實需要配置 Tailwind,可以參考 [官方文件](https://tailwindcss.com/blog/tailwindcss-v4#css-first-configuration) 來配置全域 CSS 檔案。 - -如果您有現有的 Tailwind v3 專案,還有 [升級 CLI](https://tailwindcss.com/docs/upgrade-guide) 和 [指南](https://tailwindcss.com/docs/upgrade-guide) 可供參考。 - - - -## 導入樣式 - -將 [Tailwind CSS 指令](https://tailwindcss.com/docs/functions-and-directives#directives) 添加到您的 [全域樣式表](/docs/app/getting-started/css#global-css) 中,Tailwind 將使用這些指令來注入生成的樣式,例如: - -```css filename="app/globals.css" -@import 'tailwindcss'; -``` - -在 [根佈局](/docs/app/api-reference/file-conventions/layout#root-layout) (`app/layout.tsx`) 中,導入 `globals.css` 樣式表以將樣式應用到應用程式中的每個路由。 - -```tsx filename="app/layout.tsx" switcher -import type { Metadata } from 'next' - -// 這些樣式將應用到應用程式中的每個路由 -import './globals.css' - -export const metadata: Metadata = { - title: 'Create Next App', - description: 'Generated by create next app', -} - -export default function RootLayout({ - children, -}: { - children: React.ReactNode -}) { - return ( - - {children} - - ) -} -``` - -```jsx filename="app/layout.js" switcher -// 這些樣式將應用到應用程式中的每個路由 -import './globals.css' - -export const metadata = { - title: 'Create Next App', - description: 'Generated by create next app', -} - -export default function RootLayout({ children }) { - return ( - - {children} - - ) -} -``` - -## 使用類別 - -安裝 Tailwind CSS 並添加全域樣式後,您可以在應用程式中使用 Tailwind 的工具類。 - -```tsx filename="app/page.tsx" switcher -export default function Page() { - return

Hello, Next.js!

-} -``` - -```jsx filename="app/page.js" switcher -export default function Page() { - return

Hello, Next.js!

-} -``` - -
- - - -## 導入樣式 - -將 [Tailwind CSS 指令](https://tailwindcss.com/docs/functions-and-directives#directives) 添加到您的 [全域樣式表](/docs/app/getting-started/css#global-css) 中,Tailwind 將使用這些指令來注入生成的樣式,例如: - -```css filename="styles/globals.css" -@import 'tailwindcss'; -``` - -在 [自訂應用程式檔案](/docs/pages/building-your-application/routing/custom-app) (`pages/_app.js`) 中,導入 `globals.css` 樣式表以將樣式應用到應用程式中的每個路由。 - -```tsx filename="pages/_app.tsx" switcher -// 這些樣式將應用到應用程式中的每個路由 -import '@/styles/globals.css' -import type { AppProps } from 'next/app' - -export default function App({ Component, pageProps }: AppProps) { - return -} -``` - -```jsx filename="pages/_app.js" switcher -// 這些樣式將應用到應用程式中的每個路由 -import '@/styles/globals.css' - -export default function App({ Component, pageProps }) { - return -} -``` - -## 使用類別 - -安裝 Tailwind CSS 並添加全域樣式後,您可以在應用程式中使用 Tailwind 的工具類。 - -```tsx filename="pages/index.tsx" switcher -export default function Page() { - return

Hello, Next.js!

-} -``` - -```jsx filename="pages/index.js" switcher -export default function Page() { - return

Hello, Next.js!

-} -``` - -
- -## 與 Turbopack 一起使用 - -從 Next.js 13.1 開始,Tailwind CSS 和 PostCSS 已支援 [Turbopack](https://turbo.build/pack/docs/features/css#tailwind-css)。 \ No newline at end of file diff --git a/apps/docs/content/zh-hant/docs/01-app/03-api-reference/01-directives/index.mdx b/apps/docs/content/zh-hant/docs/01-app/03-api-reference/01-directives/index.mdx new file mode 100644 index 00000000..9bd5a239 --- /dev/null +++ b/apps/docs/content/zh-hant/docs/01-app/03-api-reference/01-directives/index.mdx @@ -0,0 +1,8 @@ +--- +source-updated-at: 2025-08-09T22:43:46.028Z +translation-updated-at: 2025-08-09T22:43:46.028Z +title: 指令 (Directives) +description: 指令 (Directives) 可用於修改 Next.js 應用程式的行為。 +--- + +可用的指令如下: \ No newline at end of file diff --git a/apps/docs/content/zh-hant/docs/01-app/05-api-reference/01-directives/use-cache.mdx b/apps/docs/content/zh-hant/docs/01-app/03-api-reference/01-directives/use-cache.mdx similarity index 100% rename from apps/docs/content/zh-hant/docs/01-app/05-api-reference/01-directives/use-cache.mdx rename to apps/docs/content/zh-hant/docs/01-app/03-api-reference/01-directives/use-cache.mdx diff --git a/apps/docs/content/zh-hant/docs/01-app/03-api-reference/01-directives/use-client.mdx b/apps/docs/content/zh-hant/docs/01-app/03-api-reference/01-directives/use-client.mdx new file mode 100644 index 00000000..ac3a017f --- /dev/null +++ b/apps/docs/content/zh-hant/docs/01-app/03-api-reference/01-directives/use-client.mdx @@ -0,0 +1,125 @@ +--- +source-updated-at: 2025-08-09T22:43:46.028Z +translation-updated-at: 2025-08-09T22:43:46.028Z +title: use client +description: 了解如何使用 use client 指令來在客戶端渲染元件。 +--- + +`'use client'` 指令宣告了一個元件在**客戶端 (client side)** 渲染的進入點,應該在建立需要客戶端 JavaScript 功能的互動式使用者介面 (UI) 時使用,例如狀態管理、事件處理和存取瀏覽器 API。這是 React 的一項功能。 + +> **小知識:** +> +> 您不需要在每個包含客戶端元件 (Client Components) 的檔案中都添加 `'use client'` 指令。您只需要在那些您希望直接在伺服器元件 (Server Components) 中渲染的元件的檔案中添加它。`'use client'` 指令定義了客戶端與伺服器端的[邊界](https://nextjs.org/docs/app/building-your-application/rendering#network-boundary),從此類檔案匯出的元件將作為客戶端的進入點。 + +## 使用方法 + +要宣告客戶端元件的進入點,請在檔案的**頂部**、任何 import 語句之前添加 `'use client'` 指令: + +```tsx filename="app/components/counter.tsx" highlight={1} switcher +'use client' + +import { useState } from 'react' + +export default function Counter() { + const [count, setCount] = useState(0) + + return ( +
+

Count: {count}

+ +
+ ) +} +``` + +```jsx filename="app/components/counter.js" highlight={1} switcher +'use client' + +import { useState } from 'react' + +export default function Counter() { + const [count, setCount] = useState(0) + + return ( +
+

Count: {count}

+ +
+ ) +} +``` + +使用 `'use client'` 指令時,客戶端元件的 props 必須是[可序列化的 (serializable)](https://react.dev/reference/rsc/use-client#serializable-types)。這意味著 props 需要符合 React 在從伺服器向客戶端傳送資料時可以序列化的格式。 + +```tsx filename="app/components/counter.tsx" highlight={4} switcher +'use client' + +export default function Counter({ + onClick /* ❌ 函式不可序列化 */, +}) { + return ( +
+ +
+ ) +} +``` + +```jsx filename="app/components/counter.js" highlight={4} switcher +'use client' + +export default function Counter({ + onClick /* ❌ 函式不可序列化 */, +}) { + return ( +
+ +
+ ) +} +``` + +## 在伺服器元件中嵌套客戶端元件 + +結合伺服器元件和客戶端元件可以讓您建立既高效能又互動的應用程式: + +1. **伺服器元件 (Server Components)**:用於靜態內容、資料獲取和 SEO 友好的元素。 +2. **客戶端元件 (Client Components)**:用於需要狀態、效果或瀏覽器 API 的互動元素。 +3. **元件組合 (Component composition)**:根據需要在伺服器元件中嵌套客戶端元件,以清晰分離伺服器和客戶端邏輯。 + +在以下範例中: + +- `Header` 是一個處理靜態內容的伺服器元件。 +- `Counter` 是一個在頁面內啟用互動功能的客戶端元件。 + +```tsx filename="app/page.tsx" highlight={2,8} switcher +import Header from './header' +import Counter from './counter' // 這是一個客戶端元件 + +export default function Page() { + return ( +
+
+ +
+ ) +} +``` + +```jsx filename="app/page.js" highlight={2,8} switcher +import Header from './header' +import Counter from './counter' // 這是一個客戶端元件 + +export default function Page() { + return ( +
+
+ +
+ ) +} +``` + +## 參考資料 + +有關 `'use client'` 的更多資訊,請參閱 [React 文件](https://react.dev/reference/rsc/use-client)。 \ No newline at end of file diff --git a/apps/docs/content/zh-hant/docs/01-app/03-api-reference/01-directives/use-server.mdx b/apps/docs/content/zh-hant/docs/01-app/03-api-reference/01-directives/use-server.mdx new file mode 100644 index 00000000..a1d6afb7 --- /dev/null +++ b/apps/docs/content/zh-hant/docs/01-app/03-api-reference/01-directives/use-server.mdx @@ -0,0 +1,163 @@ +--- +source-updated-at: 2025-08-09T22:43:46.028Z +translation-updated-at: 2025-08-09T22:43:46.028Z +title: use server +description: 了解如何使用 use server 指令來在伺服器端執行程式碼。 +--- + +`use server` 指令用於標記函式或檔案在**伺服器端**執行。可以在檔案頂部使用,表示該檔案中的所有函式都是伺服器端函式;也可以在函式頂部內聯使用,將該函式標記為[伺服器函式 (Server Function)](https://19.react.dev/reference/rsc/server-functions)。這是 React 的一項功能。 + +## 在檔案頂部使用 `use server` + +以下範例展示了一個在頂部帶有 `use server` 指令的檔案。該檔案中的所有函式都會在伺服器端執行。 + +```tsx filename="app/actions.ts" highlight={1} switcher +'use server' +import { db } from '@/lib/db' // 你的資料庫客戶端 + +export async function createUser(data: { name: string; email: string }) { + const user = await db.user.create({ data }) + return user +} +``` + +```jsx filename="app/actions.js" highlight={1} switcher +'use server' +import { db } from '@/lib/db' // 你的資料庫客戶端 + +export async function createUser(data) { + const user = await db.user.create({ data }) + return user +} +``` + +### 在客戶端元件中使用伺服器函式 + +要在客戶端元件 (Client Components) 中使用伺服器函式,你需要在專用檔案中使用 `use server` 指令建立伺服器函式。這些伺服器函式隨後可以被導入客戶端和伺服器元件並執行。 + +假設你在 `actions.ts` 中有一個 `fetchUsers` 伺服器函式: + +```tsx filename="app/actions.ts" highlight={1} switcher +'use server' +import { db } from '@/lib/db' // 你的資料庫客戶端 + +export async function fetchUsers() { + const users = await db.user.findMany() + return users +} +``` + +```jsx filename="app/actions.js" highlight={1} switcher +'use server' +import { db } from '@/lib/db' // 你的資料庫客戶端 + +export async function fetchUsers() { + const users = await db.user.findMany() + return users +} +``` + +然後你可以將 `fetchUsers` 伺服器函式導入客戶端元件,並在客戶端執行它。 + +```tsx filename="app/components/my-button.tsx" highlight={1,2,8} switcher +'use client' +import { fetchUsers } from '../actions' + +export default function MyButton() { + return +} +``` + +```jsx filename="app/components/my-button.js" highlight={1,2,8} switcher +'use client' +import { fetchUsers } from '../actions' + +export default function MyButton() { + return +} +``` + +## 內聯使用 `use server` + +在以下範例中,`use server` 在函式頂部內聯使用,將其標記為[伺服器函式 (Server Function)](https://19.react.dev/reference/rsc/server-functions): + +```tsx filename="app/posts/[id]/page.tsx" switcher highlight={8} +import { EditPost } from './edit-post' +import { revalidatePath } from 'next/cache' + +export default async function PostPage({ params }: { params: { id: string } }) { + const post = await getPost(params.id) + + async function updatePost(formData: FormData) { + 'use server' + await savePost(params.id, formData) + revalidatePath(`/posts/${params.id}`) + } + + return +} +``` + +```jsx filename="app/posts/[id]/page.js" switcher highlight={8} +import { EditPost } from './edit-post' +import { revalidatePath } from 'next/cache' + +export default async function PostPage({ params }) { + const post = await getPost(params.id) + + async function updatePost(formData) { + 'use server' + await savePost(params.id, formData) + revalidatePath(`/posts/${params.id}`) + } + + return +} +``` + +## 安全性考量 + +使用 `use server` 指令時,務必確保所有伺服器端邏輯的安全性,並保護敏感資料。 + +### 身份驗證與授權 + +在執行敏感的伺服器端操作前,始終驗證使用者的身份並進行授權。 + +```tsx filename="app/actions.ts" highlight={1,7,8,9,10} switcher +'use server' + +import { db } from '@/lib/db' // 你的資料庫客戶端 +import { authenticate } from '@/lib/auth' // 你的身份驗證函式庫 + +export async function createUser( + data: { name: string; email: string }, + token: string +) { + const user = authenticate(token) + if (!user) { + throw new Error('未經授權') + } + const newUser = await db.user.create({ data }) + return newUser +} +``` + +```jsx filename="app/actions.js" highlight={1,7,8,9,10} switcher +'use server' + +import { db } from '@/lib/db' // 你的資料庫客戶端 +import { authenticate } from '@/lib/auth' // 你的身份驗證函式庫 + +export async function createUser(data, token) { + const user = authenticate(token) + if (!user) { + throw new Error('未經授權') + } + const newUser = await db.user.create({ data }) + return newUser +} +``` + +## 參考 + +更多關於 `use server` 的資訊,請參閱 [React 文件](https://react.dev/reference/rsc/use-server)。 \ No newline at end of file diff --git a/apps/docs/content/zh-hant/docs/01-app/05-api-reference/02-components/font.mdx b/apps/docs/content/zh-hant/docs/01-app/03-api-reference/02-components/font.mdx similarity index 100% rename from apps/docs/content/zh-hant/docs/01-app/05-api-reference/02-components/font.mdx rename to apps/docs/content/zh-hant/docs/01-app/03-api-reference/02-components/font.mdx diff --git a/apps/docs/content/zh-hant/docs/01-app/05-api-reference/02-components/form.mdx b/apps/docs/content/zh-hant/docs/01-app/03-api-reference/02-components/form.mdx similarity index 100% rename from apps/docs/content/zh-hant/docs/01-app/05-api-reference/02-components/form.mdx rename to apps/docs/content/zh-hant/docs/01-app/03-api-reference/02-components/form.mdx diff --git a/apps/docs/content/zh-hant/docs/01-app/05-api-reference/02-components/image.mdx b/apps/docs/content/zh-hant/docs/01-app/03-api-reference/02-components/image.mdx similarity index 100% rename from apps/docs/content/zh-hant/docs/01-app/05-api-reference/02-components/image.mdx rename to apps/docs/content/zh-hant/docs/01-app/03-api-reference/02-components/image.mdx diff --git a/apps/docs/content/zh-hant/docs/01-app/03-api-reference/02-components/index.mdx b/apps/docs/content/zh-hant/docs/01-app/03-api-reference/02-components/index.mdx new file mode 100644 index 00000000..67921ee9 --- /dev/null +++ b/apps/docs/content/zh-hant/docs/01-app/03-api-reference/02-components/index.mdx @@ -0,0 +1,8 @@ +--- +source-updated-at: 2025-08-09T22:43:46.028Z +translation-updated-at: 2025-08-09T22:43:46.028Z +title: 元件 +description: Next.js 內建元件的 API 參考文件。 +--- + +{/* 此文件的內容在應用程式路由器和頁面路由器之間共享。您可以使用 `內容` 元件來新增專屬於頁面路由器的內容。任何共享內容都不應包裹在元件中。 */} \ No newline at end of file diff --git a/apps/docs/content/zh-hant/docs/01-app/05-api-reference/02-components/link.mdx b/apps/docs/content/zh-hant/docs/01-app/03-api-reference/02-components/link.mdx similarity index 100% rename from apps/docs/content/zh-hant/docs/01-app/05-api-reference/02-components/link.mdx rename to apps/docs/content/zh-hant/docs/01-app/03-api-reference/02-components/link.mdx diff --git a/apps/docs/content/zh-hant/docs/01-app/05-api-reference/02-components/script.mdx b/apps/docs/content/zh-hant/docs/01-app/03-api-reference/02-components/script.mdx similarity index 100% rename from apps/docs/content/zh-hant/docs/01-app/05-api-reference/02-components/script.mdx rename to apps/docs/content/zh-hant/docs/01-app/03-api-reference/02-components/script.mdx diff --git a/apps/docs/content/zh-hant/docs/01-app/05-api-reference/03-file-conventions/01-metadata/app-icons.mdx b/apps/docs/content/zh-hant/docs/01-app/03-api-reference/03-file-conventions/01-metadata/app-icons.mdx similarity index 100% rename from apps/docs/content/zh-hant/docs/01-app/05-api-reference/03-file-conventions/01-metadata/app-icons.mdx rename to apps/docs/content/zh-hant/docs/01-app/03-api-reference/03-file-conventions/01-metadata/app-icons.mdx diff --git a/apps/docs/content/zh-hant/docs/01-app/05-api-reference/03-file-conventions/01-metadata/index.mdx b/apps/docs/content/zh-hant/docs/01-app/03-api-reference/03-file-conventions/01-metadata/index.mdx similarity index 100% rename from apps/docs/content/zh-hant/docs/01-app/05-api-reference/03-file-conventions/01-metadata/index.mdx rename to apps/docs/content/zh-hant/docs/01-app/03-api-reference/03-file-conventions/01-metadata/index.mdx diff --git a/apps/docs/content/zh-hant/docs/01-app/05-api-reference/03-file-conventions/01-metadata/manifest.mdx b/apps/docs/content/zh-hant/docs/01-app/03-api-reference/03-file-conventions/01-metadata/manifest.mdx similarity index 100% rename from apps/docs/content/zh-hant/docs/01-app/05-api-reference/03-file-conventions/01-metadata/manifest.mdx rename to apps/docs/content/zh-hant/docs/01-app/03-api-reference/03-file-conventions/01-metadata/manifest.mdx diff --git a/apps/docs/content/zh-hant/docs/01-app/05-api-reference/03-file-conventions/01-metadata/opengraph-image.mdx b/apps/docs/content/zh-hant/docs/01-app/03-api-reference/03-file-conventions/01-metadata/opengraph-image.mdx similarity index 100% rename from apps/docs/content/zh-hant/docs/01-app/05-api-reference/03-file-conventions/01-metadata/opengraph-image.mdx rename to apps/docs/content/zh-hant/docs/01-app/03-api-reference/03-file-conventions/01-metadata/opengraph-image.mdx diff --git a/apps/docs/content/zh-hant/docs/01-app/05-api-reference/03-file-conventions/01-metadata/robots.mdx b/apps/docs/content/zh-hant/docs/01-app/03-api-reference/03-file-conventions/01-metadata/robots.mdx similarity index 100% rename from apps/docs/content/zh-hant/docs/01-app/05-api-reference/03-file-conventions/01-metadata/robots.mdx rename to apps/docs/content/zh-hant/docs/01-app/03-api-reference/03-file-conventions/01-metadata/robots.mdx diff --git a/apps/docs/content/zh-hant/docs/01-app/05-api-reference/03-file-conventions/01-metadata/sitemap.mdx b/apps/docs/content/zh-hant/docs/01-app/03-api-reference/03-file-conventions/01-metadata/sitemap.mdx similarity index 100% rename from apps/docs/content/zh-hant/docs/01-app/05-api-reference/03-file-conventions/01-metadata/sitemap.mdx rename to apps/docs/content/zh-hant/docs/01-app/03-api-reference/03-file-conventions/01-metadata/sitemap.mdx diff --git a/apps/docs/content/zh-hant/docs/01-app/03-api-reference/03-file-conventions/default.mdx b/apps/docs/content/zh-hant/docs/01-app/03-api-reference/03-file-conventions/default.mdx new file mode 100644 index 00000000..276201c9 --- /dev/null +++ b/apps/docs/content/zh-hant/docs/01-app/03-api-reference/03-file-conventions/default.mdx @@ -0,0 +1,60 @@ +--- +source-updated-at: 2025-08-09T22:43:46.028Z +translation-updated-at: 2025-08-09T22:43:46.028Z +title: default.js +description: default.js 檔案的 API 參考文檔 +related: + title: 深入了解平行路由 (Parallel Routes) + links: + - app/api-reference/file-conventions/parallel-routes +--- + +`default.js` 檔案用於在 [平行路由 (Parallel Routes)](/docs/app/api-reference/file-conventions/parallel-routes) 中提供後備渲染,當 Next.js 在完整頁面載入後無法恢復 [插槽 (slot)](/docs/app/api-reference/file-conventions/parallel-routes#slots) 的活動狀態時使用。 + +在 [軟導航 (soft navigation)](/docs/app/getting-started/linking-and-navigating#client-side-transitions) 期間,Next.js 會追蹤每個插槽的活動 _狀態_ (子頁面)。然而,對於硬導航 (完整頁面載入),Next.js 無法恢復活動狀態。在這種情況下,會為不符合當前 URL 的子頁面渲染 `default.js` 檔案。 + +考慮以下資料夾結構。`@team` 插槽有一個 `settings` 頁面,但 `@analytics` 沒有。 + +平行路由未匹配的路由 + +當導航至 `/settings` 時,`@team` 插槽會渲染 `settings` 頁面,同時保持 `@analytics` 插槽當前活動的頁面。 + +在重新整理時,Next.js 會為 `@analytics` 渲染 `default.js`。如果 `default.js` 不存在,則會改為渲染 `404`。 + +此外,由於 `children` 是一個隱式插槽,您也需要建立一個 `default.js` 檔案,以便在 Next.js 無法恢復父頁面的活動狀態時為 `children` 提供後備渲染。 + +## 參考 + +### `params` (選用) + +一個解析為包含從根段到插槽子頁面的 [動態路由參數 (dynamic route parameters)](/docs/app/api-reference/file-conventions/dynamic-routes) 物件的 Promise。例如: + +```tsx filename="app/[artist]/@sidebar/default.js" switcher +export default async function Default({ + params, +}: { + params: Promise<{ artist: string }> +}) { + const { artist } = await params +} +``` + +```jsx filename="app/[artist]/@sidebar/default.js" switcher +export default async function Default({ params }) { + const { artist } = await params +} +``` + +| 範例 | URL | `params` | +| ---------------------------------------- | ------------ | -------------------------------------------- | +| `app/[artist]/@sidebar/default.js` | `/zack` | `Promise<{ artist: 'zack' }>` | +| `app/[artist]/[album]/@sidebar/default.js` | `/zack/next` | `Promise<{ artist: 'zack', album: 'next' }>` | + +- 由於 `params` 屬性是一個 Promise,您必須使用 `async/await` 或 React 的 [`use`](https://react.dev/reference/react/use) 函式來存取值。 + - 在版本 14 及更早版本中,`params` 是一個同步屬性。為了向後兼容,在 Next.js 15 中您仍然可以同步存取它,但此行為將在未來被棄用。 \ No newline at end of file diff --git a/apps/docs/content/zh-hant/docs/01-app/05-api-reference/03-file-conventions/dynamic-routes.mdx b/apps/docs/content/zh-hant/docs/01-app/03-api-reference/03-file-conventions/dynamic-routes.mdx similarity index 100% rename from apps/docs/content/zh-hant/docs/01-app/05-api-reference/03-file-conventions/dynamic-routes.mdx rename to apps/docs/content/zh-hant/docs/01-app/03-api-reference/03-file-conventions/dynamic-routes.mdx diff --git a/apps/docs/content/zh-hant/docs/01-app/05-api-reference/03-file-conventions/error.mdx b/apps/docs/content/zh-hant/docs/01-app/03-api-reference/03-file-conventions/error.mdx similarity index 100% rename from apps/docs/content/zh-hant/docs/01-app/05-api-reference/03-file-conventions/error.mdx rename to apps/docs/content/zh-hant/docs/01-app/03-api-reference/03-file-conventions/error.mdx diff --git a/apps/docs/content/zh-hant/docs/01-app/03-api-reference/03-file-conventions/forbidden.mdx b/apps/docs/content/zh-hant/docs/01-app/03-api-reference/03-file-conventions/forbidden.mdx new file mode 100644 index 00000000..a6669d46 --- /dev/null +++ b/apps/docs/content/zh-hant/docs/01-app/03-api-reference/03-file-conventions/forbidden.mdx @@ -0,0 +1,52 @@ +--- +source-updated-at: 2025-08-09T22:43:46.028Z +translation-updated-at: 2025-08-09T22:43:46.028Z +title: forbidden.js +description: 關於 forbidden.js 特殊檔案的 API 參考文件。 +related: + links: + - app/api-reference/functions/forbidden +version: experimental +--- + +**forbidden** 檔案用於在認證過程中呼叫 [`forbidden`](/docs/app/api-reference/functions/forbidden) 函數時渲染 UI。除了允許您自訂 UI 外,Next.js 還會回傳 `403` 狀態碼。 + +```tsx filename="app/forbidden.tsx" switcher +import Link from 'next/link' + +export default function Forbidden() { + return ( +
+

Forbidden

+

You are not authorized to access this resource.

+ Return Home +
+ ) +} +``` + +```jsx filename="app/forbidden.jsx" switcher +import Link from 'next/link' + +export default function Forbidden() { + return ( +
+

Forbidden

+

You are not authorized to access this resource.

+ Return Home +
+ ) +} +``` + +## 參考文件 + +### 屬性 + +`forbidden.js` 元件不接受任何屬性。 + +## 版本歷史 + +| 版本 | 變更內容 | +| ---------- | --------------------------- | +| `v15.1.0` | 新增 `forbidden.js` 功能。 | \ No newline at end of file diff --git a/apps/docs/content/zh-hant/docs/01-app/03-api-reference/03-file-conventions/index.mdx b/apps/docs/content/zh-hant/docs/01-app/03-api-reference/03-file-conventions/index.mdx new file mode 100644 index 00000000..2a668663 --- /dev/null +++ b/apps/docs/content/zh-hant/docs/01-app/03-api-reference/03-file-conventions/index.mdx @@ -0,0 +1,6 @@ +--- +source-updated-at: 2025-08-09T22:43:46.028Z +translation-updated-at: 2025-08-09T22:43:46.028Z +title: 檔案系統慣例 +description: Next.js 檔案系統慣例的 API 參考文件。 +--- \ No newline at end of file diff --git a/apps/docs/content/zh-hant/docs/01-app/03-api-reference/03-file-conventions/instrumentation.mdx b/apps/docs/content/zh-hant/docs/01-app/03-api-reference/03-file-conventions/instrumentation.mdx new file mode 100644 index 00000000..f1e48a25 --- /dev/null +++ b/apps/docs/content/zh-hant/docs/01-app/03-api-reference/03-file-conventions/instrumentation.mdx @@ -0,0 +1,141 @@ +--- +source-updated-at: 2025-08-09T22:43:46.028Z +translation-updated-at: 2025-08-09T22:43:46.028Z +title: instrumentation.js +description: 關於 instrumentation.js 檔案的 API 參考文件。 +related: + title: 深入了解 Instrumentation + links: + - app/guides/instrumentation +--- + +`instrumentation.js|ts` 檔案用於將可觀測性工具整合到您的應用程式中,讓您可以追蹤效能和行為,並在生產環境中除錯問題。 + +要使用它,請將檔案放在應用程式的**根目錄**,或如果使用 [`src` 資料夾](/docs/app/api-reference/file-conventions/src-folder) 則放在其中。 + +## 匯出項目 + +### `register` (選用) + +該檔案匯出一個 `register` 函式,當新的 Next.js 伺服器實例初始化時會**呼叫一次**。`register` 可以是非同步函式。 + +```ts filename="instrumentation.ts" switcher +import { registerOTel } from '@vercel/otel' + +export function register() { + registerOTel('next-app') +} +``` + +```js filename="instrumentation.js" switcher +import { registerOTel } from '@vercel/otel' + +export function register() { + registerOTel('next-app') +} +``` + +### `onRequestError` (選用) + +您可以選擇匯出一個 `onRequestError` 函式,以將**伺服器**錯誤追蹤到任何自訂的可觀測性提供者。 + +- 如果您在 `onRequestError` 中執行任何非同步任務,請確保它們被等待。`onRequestError` 會在 Next.js 伺服器捕獲錯誤時觸發。 +- `error` 實例可能不是拋出的原始錯誤實例,因為如果在伺服器元件渲染期間遇到錯誤,它可能會被 React 處理。如果發生這種情況,您可以使用錯誤上的 `digest` 屬性來識別實際的錯誤類型。 + +```ts filename="instrumentation.ts" switcher +import { type Instrumentation } from 'next' + +export const onRequestError: Instrumentation.onRequestError = async ( + err, + request, + context +) => { + await fetch('https://.../report-error', { + method: 'POST', + body: JSON.stringify({ + message: err.message, + request, + context, + }), + headers: { + 'Content-Type': 'application/json', + }, + }) +} +``` + +```js filename="instrumentation.js" switcher +export async function onRequestError(err, request, context) { + await fetch('https://.../report-error', { + method: 'POST', + body: JSON.stringify({ + message: err.message, + request, + context, + }), + headers: { + 'Content-Type': 'application/json', + }, + }) +} +``` + +#### 參數 + +該函式接受三個參數:`error`、`request` 和 `context`。 + +```ts filename="Types" +export function onRequestError( + error: { digest: string } & Error, + request: { + path: string // 資源路徑,例如 /blog?name=foo + method: string // 請求方法,例如 GET、POST 等 + headers: { [key: string]: string } + }, + context: { + routerKind: 'Pages Router' | 'App Router' // 路由器類型 + routePath: string // 路由檔案路徑,例如 /app/blog/[dynamic] + routeType: 'render' | 'route' | 'action' | 'middleware' // 發生錯誤的上下文 + renderSource: + | 'react-server-components' + | 'react-server-components-payload' + | 'server-rendering' + revalidateReason: 'on-demand' | 'stale' | undefined // undefined 表示沒有重新驗證的正常請求 + renderType: 'dynamic' | 'dynamic-resume' // 'dynamic-resume' 用於 PPR + } +): void | Promise +``` + +- `error`: 捕獲的錯誤本身(類型始終為 `Error`),以及 `digest` 屬性,這是錯誤的唯一 ID。 +- `request`: 與錯誤相關聯的唯讀請求資訊。 +- `context`: 發生錯誤的上下文。這可以是路由器的類型(App 或 Pages Router),和/或(伺服器元件 (`'render'`)、路由處理程式 (`'route'`)、伺服器動作 (`'action'`) 或中介軟體 (`'middleware'`))。 + +### 指定執行環境 + +`instrumentation.js` 檔案在 Node.js 和 Edge 執行環境中均可使用,但您可以使用 `process.env.NEXT_RUNTIME` 來針對特定執行環境。 + +```js filename="instrumentation.js" +export function register() { + if (process.env.NEXT_RUNTIME === 'edge') { + return require('./register.edge') + } else { + return require('./register.node') + } +} + +export function onRequestError() { + if (process.env.NEXT_RUNTIME === 'edge') { + return require('./on-request-error.edge') + } else { + return require('./on-request-error.node') + } +} +``` + +## 版本歷史 + +| 版本 | 變更內容 | +| ---------- | ------------------------------------------------------- | +| `v15.0.0` | 引入 `onRequestError`,`instrumentation` 穩定版 | +| `v14.0.4` | Turbopack 支援 `instrumentation` | +| `v13.2.0` | `instrumentation` 作為實驗性功能引入 | \ No newline at end of file diff --git a/apps/docs/content/zh-hant/docs/01-app/05-api-reference/03-file-conventions/intercepting-routes.mdx b/apps/docs/content/zh-hant/docs/01-app/03-api-reference/03-file-conventions/intercepting-routes.mdx similarity index 100% rename from apps/docs/content/zh-hant/docs/01-app/05-api-reference/03-file-conventions/intercepting-routes.mdx rename to apps/docs/content/zh-hant/docs/01-app/03-api-reference/03-file-conventions/intercepting-routes.mdx diff --git a/apps/docs/content/zh-hant/docs/01-app/05-api-reference/03-file-conventions/layout.mdx b/apps/docs/content/zh-hant/docs/01-app/03-api-reference/03-file-conventions/layout.mdx similarity index 100% rename from apps/docs/content/zh-hant/docs/01-app/05-api-reference/03-file-conventions/layout.mdx rename to apps/docs/content/zh-hant/docs/01-app/03-api-reference/03-file-conventions/layout.mdx diff --git a/apps/docs/content/zh-hant/docs/01-app/03-api-reference/03-file-conventions/loading.mdx b/apps/docs/content/zh-hant/docs/01-app/03-api-reference/03-file-conventions/loading.mdx new file mode 100644 index 00000000..45d47062 --- /dev/null +++ b/apps/docs/content/zh-hant/docs/01-app/03-api-reference/03-file-conventions/loading.mdx @@ -0,0 +1,169 @@ +--- +source-updated-at: 2025-08-09T22:43:46.028Z +translation-updated-at: 2025-08-09T22:43:46.028Z +title: loading.js +description: loading.js 檔案的 API 參考文檔 +--- + +特殊檔案 `loading.js` 可幫助您使用 [React Suspense](https://react.dev/reference/react/Suspense) 建立有意義的載入介面。透過此約定,您可以在路由區段的內容串流載入時,從伺服器顯示[即時載入狀態](#instant-loading-states)。一旦完成,新內容會自動替換顯示。 + +載入介面 + +```tsx filename="app/feed/loading.tsx" switcher +export default function Loading() { + // 或自訂載入骨架元件 + return

載入中...

+} +``` + +```jsx filename="app/feed/loading.js" switcher +export default function Loading() { + // 或自訂載入骨架元件 + return

載入中...

+} +``` + +在 `loading.js` 檔案中,您可以加入任何輕量級的載入介面。您可能會發現使用 [React 開發者工具](https://react.dev/learn/react-developer-tools)手動切換 Suspense 邊界很有幫助。 + +預設情況下,此檔案是[伺服器元件](/docs/app/getting-started/server-and-client-components),但也可以透過 `"use client"` 指令作為客戶端元件使用。 + +## 參考 + +### 參數 + +載入介面元件不接受任何參數。 + +## 行為 + +### 導航 + +- 備用介面會[預先載取](/docs/app/getting-started/linking-and-navigating#prefetching),使導航立即進行,除非預載取尚未完成。 +- 導航可中斷,意味著變更路由無需等待路由內容完全載入後再導航至其他路由。 +- 共享佈局在新路由區段載入時保持可互動。 + +### 即時載入狀態 + +即時載入狀態是導航時立即顯示的備用介面。您可以預先渲染載入指示器,如骨架或旋轉圖示,或是未來畫面的重要部分,如封面照片、標題等。這有助於使用者理解應用程式正在回應,並提供更好的使用者體驗。 + +透過在資料夾內新增 `loading.js` 檔案來建立載入狀態。 + +loading.js 特殊檔案 + +```tsx filename="app/dashboard/loading.tsx" switcher +export default function Loading() { + // 您可以在 Loading 中加入任何介面,包括骨架。 + return +} +``` + +```jsx filename="app/dashboard/loading.js" switcher +export default function Loading() { + // 您可以在 Loading 中加入任何介面,包括骨架。 + return +} +``` + +在同一資料夾中,`loading.js` 會嵌套在 `layout.js` 內。它會自動將 `page.js` 檔案及其下方子元件包裹在 `` 邊界中。 + +loading.js 概覽 + +### SEO + +- Next.js 會等待 [`generateMetadata`](/docs/app/api-reference/functions/generate-metadata) 內的資料載取完成後,再將介面串流至客戶端。這保證串流回應的第一部分包含 `` 標籤。 +- 由於串流是伺服器渲染,不會影響 SEO。您可以使用 Google 的[豐富結果測試](https://search.google.com/test/rich-results)工具查看頁面在 Google 網路爬蟲中的顯示方式,並檢視序列化的 HTML ([來源](https://web.dev/rendering-on-the-web/#seo-considerations))。 + +### 狀態碼 + +串流時會回傳 `200` 狀態碼,表示請求成功。 + +伺服器仍可在串流內容本身中向客戶端傳達錯誤或問題,例如使用 [`redirect`](/docs/app/api-reference/functions/redirect) 或 [`notFound`](/docs/app/api-reference/functions/not-found) 時。由於回應標頭已傳送至客戶端,回應的狀態碼無法更新。這不影響 SEO。 + +### 瀏覽器限制 + +[某些瀏覽器](https://bugs.webkit.org/show_bug.cgi?id=252413)會緩衝串流回應。您可能看不到串流回應,直到回應超過 1024 位元組。這通常只影響「hello world」應用程式,而不影響實際應用程式。 + +## 平台支援 + +| 部署選項 | 支援情況 | +| ------------------------------------------------------------ | ---------------- | +| [Node.js 伺服器](/docs/app/getting-started/deploying#nodejs-server) | 是 | +| [Docker 容器](/docs/app/getting-started/deploying#docker) | 是 | +| [靜態匯出](/docs/app/getting-started/deploying#static-export) | 否 | +| [轉接器](/docs/app/getting-started/deploying#adapters) | 依平台而定 | + +了解如何[設定串流](/docs/app/guides/self-hosting#streaming-and-suspense)當自行託管 Next.js 時。 + +## 範例 + +### 使用 Suspense 串流 + +除了 `loading.js`,您也可以手動為自己的介面元件建立 Suspense 邊界。App Router 支援使用 [Suspense](https://react.dev/reference/react/Suspense) 串流。 + +`` 的工作原理是包裹執行非同步操作(例如載取資料)的元件,在操作進行時顯示備用介面(例如骨架、旋轉圖示),並在操作完成後替換為您的元件。 + +```tsx filename="app/dashboard/page.tsx" switcher +import { Suspense } from 'react' +import { PostFeed, Weather } from './Components' + +export default function Posts() { + return ( +
+ 載入動態...

}> + +
+ 載入天氣...

}> + +
+
+ ) +} +``` + +```jsx filename="app/dashboard/page.js" switcher +import { Suspense } from 'react' +import { PostFeed, Weather } from './Components' + +export default function Posts() { + return ( +
+ 載入動態...

}> + +
+ 載入天氣...

}> + +
+
+ ) +} +``` + +使用 Suspense 可獲得以下好處: + +1. **串流伺服器渲染** - 從伺服器逐步渲染 HTML 至客戶端。 +2. **選擇性水合** - React 根據使用者互動優先處理哪些元件先變為可互動。 + +更多 Suspense 範例和使用案例,請參閱 [React 文件](https://react.dev/reference/react/Suspense)。 + +## 版本歷史 + +| 版本 | 變更 | +| ---------- | --------------------- | +| `v13.0.0` | 引入 `loading` 功能。 | \ No newline at end of file diff --git a/apps/docs/content/zh-hant/docs/01-app/05-api-reference/03-file-conventions/mdx-components.mdx b/apps/docs/content/zh-hant/docs/01-app/03-api-reference/03-file-conventions/mdx-components.mdx similarity index 100% rename from apps/docs/content/zh-hant/docs/01-app/05-api-reference/03-file-conventions/mdx-components.mdx rename to apps/docs/content/zh-hant/docs/01-app/03-api-reference/03-file-conventions/mdx-components.mdx diff --git a/apps/docs/content/zh-hant/docs/01-app/03-building-your-application/01-routing/14-middleware.mdx b/apps/docs/content/zh-hant/docs/01-app/03-api-reference/03-file-conventions/middleware.mdx similarity index 100% rename from apps/docs/content/zh-hant/docs/01-app/03-building-your-application/01-routing/14-middleware.mdx rename to apps/docs/content/zh-hant/docs/01-app/03-api-reference/03-file-conventions/middleware.mdx diff --git a/apps/docs/content/zh-hant/docs/01-app/05-api-reference/03-file-conventions/page.mdx b/apps/docs/content/zh-hant/docs/01-app/03-api-reference/03-file-conventions/page.mdx similarity index 100% rename from apps/docs/content/zh-hant/docs/01-app/05-api-reference/03-file-conventions/page.mdx rename to apps/docs/content/zh-hant/docs/01-app/03-api-reference/03-file-conventions/page.mdx diff --git a/apps/docs/content/zh-hant/docs/01-app/05-api-reference/03-file-conventions/parallel-routes.mdx b/apps/docs/content/zh-hant/docs/01-app/03-api-reference/03-file-conventions/parallel-routes.mdx similarity index 100% rename from apps/docs/content/zh-hant/docs/01-app/05-api-reference/03-file-conventions/parallel-routes.mdx rename to apps/docs/content/zh-hant/docs/01-app/03-api-reference/03-file-conventions/parallel-routes.mdx diff --git a/apps/docs/content/zh-hant/docs/01-app/03-api-reference/03-file-conventions/public-folder.mdx b/apps/docs/content/zh-hant/docs/01-app/03-api-reference/03-file-conventions/public-folder.mdx new file mode 100644 index 00000000..1686bf45 --- /dev/null +++ b/apps/docs/content/zh-hant/docs/01-app/03-api-reference/03-file-conventions/public-folder.mdx @@ -0,0 +1,47 @@ +--- +source-updated-at: 2025-08-09T22:43:46.028Z +translation-updated-at: 2025-08-09T22:43:46.028Z +title: public 資料夾 +nav_title: public +description: Next.js 允許您在 public 目錄中提供靜態檔案,例如圖片。您可以在這裡了解它的運作方式。 +--- + +{/* 此文件的內容在 app 和 pages 路由器之間共享。您可以使用 `內容` 元件來新增專屬於 Pages 路由器的內容。任何共享內容都不應包裹在元件中。*/} + +Next.js 可以在根目錄下的 `public` 資料夾中提供靜態檔案,例如圖片。`public` 內的檔案可以透過從基礎 URL (`/`) 開始的路徑在程式碼中引用。 + +例如,檔案 `public/avatars/me.png` 可以透過訪問 `/avatars/me.png` 路徑來查看。顯示該圖片的程式碼可能如下: + +```jsx filename="avatar.js" +import Image from 'next/image' + +export function Avatar({ id, alt }) { + return {alt} +} + +export function AvatarOfMe() { + return +} +``` + +## 快取 + +Next.js 無法安全地快取 `public` 資料夾中的資源,因為它們可能會變更。預設套用的快取標頭為: + +```jsx +Cache-Control: public, max-age=0 +``` + +## Robots、Favicon 及其他檔案 + + + +此資料夾也適用於 `robots.txt`、`favicon.ico`、Google 網站驗證以及任何其他靜態檔案(包括 `.html`)。但請確保不要有與 `pages/` 目錄中檔案同名的靜態檔案,這將導致錯誤。[了解更多](/docs/messages/conflicting-public-file-page)。 + + + + + +對於靜態元資料檔案,例如 `robots.txt`、`favicon.ico` 等,您應該在 `app` 資料夾中使用[特殊元資料檔案](/docs/app/api-reference/file-conventions/metadata)。 + + \ No newline at end of file diff --git a/apps/docs/content/zh-hant/docs/01-app/03-api-reference/03-file-conventions/route-groups.mdx b/apps/docs/content/zh-hant/docs/01-app/03-api-reference/03-file-conventions/route-groups.mdx new file mode 100644 index 00000000..2334fba3 --- /dev/null +++ b/apps/docs/content/zh-hant/docs/01-app/03-api-reference/03-file-conventions/route-groups.mdx @@ -0,0 +1,34 @@ +--- +source-updated-at: 2025-08-09T22:43:46.028Z +translation-updated-at: 2025-08-09T22:43:46.028Z +title: 路由群組 (Route Groups) +description: 路由群組可用於將 Next.js 應用程式劃分為不同區塊。 +--- + +路由群組是一種資料夾命名慣例,可讓您按類別或團隊來組織路由。 + +## 命名慣例 + +建立路由群組的方式是將資料夾名稱用括號包起來:`(資料夾名稱)`。 + +此慣例表示該資料夾僅用於組織目的,**不應包含**在路由的 URL 路徑中。 + +使用路由群組的資料夾結構範例 + +## 使用情境 + +- 按團隊、關注點或功能組織路由 +- 定義多個 [根佈局 (root layouts)](/docs/app/api-reference/file-conventions/layout#root-layout) +- 讓特定路由區段選擇共享佈局,同時排除其他區段 + +## 注意事項 + +- **完整頁面載入**:若在使用了不同根佈局的路由之間導航,會觸發完整頁面重新載入。例如從使用 `app/(shop)/layout.js` 的 `/cart` 導航到使用 `app/(marketing)/layout.js` 的 `/blog`。此情況**僅**適用於多個根佈局的情況。 +- **路徑衝突**:不同群組中的路由不應解析為相同的 URL 路徑。例如 `(marketing)/about/page.js` 和 `(shop)/about/page.js` 都會解析到 `/about` 並導致錯誤。 +- **頂層根佈局**:若使用多個根佈局但沒有頂層的 `layout.js` 檔案,請確保首頁路由 (/) 定義在其中一個路由群組內,例如 `app/(marketing)/page.js`。 \ No newline at end of file diff --git a/apps/docs/content/zh-hant/docs/01-app/05-api-reference/03-file-conventions/route-segment-config.mdx b/apps/docs/content/zh-hant/docs/01-app/03-api-reference/03-file-conventions/route-segment-config.mdx similarity index 100% rename from apps/docs/content/zh-hant/docs/01-app/05-api-reference/03-file-conventions/route-segment-config.mdx rename to apps/docs/content/zh-hant/docs/01-app/03-api-reference/03-file-conventions/route-segment-config.mdx diff --git a/apps/docs/content/zh-hant/docs/01-app/03-building-your-application/01-routing/13-route-handlers.mdx b/apps/docs/content/zh-hant/docs/01-app/03-api-reference/03-file-conventions/route.mdx similarity index 100% rename from apps/docs/content/zh-hant/docs/01-app/03-building-your-application/01-routing/13-route-handlers.mdx rename to apps/docs/content/zh-hant/docs/01-app/03-api-reference/03-file-conventions/route.mdx diff --git a/apps/docs/content/zh-hant/docs/01-app/03-api-reference/03-file-conventions/src-folder.mdx b/apps/docs/content/zh-hant/docs/01-app/03-api-reference/03-file-conventions/src-folder.mdx new file mode 100644 index 00000000..251730a0 --- /dev/null +++ b/apps/docs/content/zh-hant/docs/01-app/03-api-reference/03-file-conventions/src-folder.mdx @@ -0,0 +1,37 @@ +--- +source-updated-at: 2025-08-09T22:43:46.028Z +translation-updated-at: 2025-08-09T22:43:46.028Z +title: src 資料夾 +nav_title: src +description: 可將頁面儲存在 `src` 資料夾中,作為根目錄 `pages` 的替代方案。 +related: + links: + - app/getting-started/project-structure +--- + +{/* 此文件內容同時適用於 app 和 pages 路由。您可以使用 `內容` 元件來新增專屬於 Pages Router 的內容。任何共享內容不應被包裹在元件中。 */} + +除了在專案根目錄中建立特殊的 Next.js `app` 或 `pages` 目錄外,Next.js 也支援將應用程式程式碼放在 `src` 資料夾下的常見模式。 + +這種做法可將應用程式程式碼與主要存放在專案根目錄的專案設定檔分開,這是一些個人和團隊偏好的方式。 + +要使用 `src` 資料夾,請將 `app` 路由資料夾或 `pages` 路由資料夾分別移動到 `src/app` 或 `src/pages`。 + +包含 `src` 資料夾的範例專案結構 + +> **須知事項**: +> +> - `/public` 目錄應保留在專案的根目錄中。 +> - 設定檔如 `package.json`、`next.config.js` 和 `tsconfig.json` 應保留在專案根目錄。 +> - `.env.*` 檔案應保留在專案根目錄。 +> - 如果根目錄中存在 `app` 或 `pages`,則 `src/app` 或 `src/pages` 將被忽略。 +> - 如果您使用 `src`,可能還需要移動其他應用程式資料夾,例如 `/components` 或 `/lib`。 +> - 如果您使用中介軟體 (Middleware),請確保將其放置在 `src` 資料夾內。 +> - 如果您使用 Tailwind CSS,需要在 `tailwind.config.js` 檔案的 [content 區段](https://tailwindcss.com/docs/content-configuration) 中加入 `/src` 前綴。 +> - 如果您使用 TypeScript 路徑進行導入 (例如 `@/*`),應更新 `tsconfig.json` 中的 `paths` 物件以包含 `src/`。 \ No newline at end of file diff --git a/apps/docs/content/zh-hant/docs/01-app/03-api-reference/03-file-conventions/template.mdx b/apps/docs/content/zh-hant/docs/01-app/03-api-reference/03-file-conventions/template.mdx new file mode 100644 index 00000000..025e596a --- /dev/null +++ b/apps/docs/content/zh-hant/docs/01-app/03-api-reference/03-file-conventions/template.mdx @@ -0,0 +1,74 @@ +--- +source-updated-at: 2025-08-09T22:43:46.028Z +translation-updated-at: 2025-08-09T22:43:46.028Z +title: template.js +description: template.js 檔案的 API 參考文件。 +--- + +**模板 (template)** 檔案與 [layout](/docs/app/getting-started/layouts-and-pages#creating-a-layout) 類似,都是用來包裹佈局或頁面。不同於佈局會跨路由保持狀態,模板會被賦予一個唯一鍵值,這意味著其內部的客戶端元件 (Client Components) 在導航時會重置狀態。 + +以下情境適合使用模板: + +- 需要在導航時重新同步 `useEffect` +- 需要在導航時重置子客戶端元件的狀態(例如輸入欄位) +- 需要變更框架的預設行為(例如佈局中的 Suspense 邊界僅在首次載入時顯示回退內容,而模板會在每次導航時顯示) + +## 約定 + +在 `template.js` 檔案中匯出預設的 React 元件即可定義模板。該元件應接受一個 `children` 屬性。 + +template.js 特殊檔案 + +```tsx filename="app/template.tsx" switcher +export default function Template({ children }: { children: React.ReactNode }) { + return
{children}
+} +``` + +```jsx filename="app/template.js" switcher +export default function Template({ children }) { + return
{children}
+} +``` + +在巢狀結構中,`template.js` 會渲染在佈局與其子元件之間。以下是簡化的輸出範例: + +```jsx filename="Output" + + {/* 注意模板會被賦予唯一鍵值 */} + + +``` + +## 屬性 + +### `children` (必填) + +模板接受一個 `children` 屬性。 + +```jsx filename="Output" + + {/* 注意模板會自動獲得唯一鍵值 */} + + +``` + +## 行為特性 + +- **伺服器元件 (Server Components)**:預設情況下,模板是伺服器元件 +- **導航時重新掛載**:模板會自動獲得唯一鍵值,導航至新路由會導致模板及其子元件重新掛載 +- **狀態重置**:模板內部的任何客戶端元件在導航時都會重置狀態 +- **副作用重新執行**:像 `useEffect` 這樣的副作用會在元件重新掛載時重新同步 +- **DOM 重置**:模板內部的 DOM 元素會完全重新建立 + +## 版本歷史 + +| 版本 | 變更內容 | +| ---------- | ---------------------- | +| `v13.0.0` | 新增 `template` 功能 | \ No newline at end of file diff --git a/apps/docs/content/zh-hant/docs/01-app/03-api-reference/03-file-conventions/unauthorized.mdx b/apps/docs/content/zh-hant/docs/01-app/03-api-reference/03-file-conventions/unauthorized.mdx new file mode 100644 index 00000000..be7cc903 --- /dev/null +++ b/apps/docs/content/zh-hant/docs/01-app/03-api-reference/03-file-conventions/unauthorized.mdx @@ -0,0 +1,116 @@ +--- +source-updated-at: 2025-08-09T22:43:46.028Z +translation-updated-at: 2025-08-09T22:43:46.028Z +title: unauthorized.js +description: 關於 unauthorized.js 特殊檔案的 API 參考文件。 +related: + links: + - app/api-reference/functions/unauthorized +version: experimental +--- + +**unauthorized** 檔案用於在認證過程中呼叫 [`unauthorized`](/docs/app/api-reference/functions/unauthorized) 函式時渲染 UI。除了允許您自訂 UI 外,Next.js 還會回傳 `401` 狀態碼。 + +```tsx filename="app/unauthorized.tsx" switcher +import Login from '@/app/components/Login' + +export default function Unauthorized() { + return ( +
+

401 - Unauthorized

+

Please log in to access this page.

+ +
+ ) +} +``` + +```jsx filename="app/unauthorized.js" switcher +import Login from '@/app/components/Login' + +export default function Unauthorized() { + return ( +
+

401 - Unauthorized

+

Please log in to access this page.

+ +
+ ) +} +``` + +## 參考 + +### Props + +`unauthorized.js` 元件不接受任何 props。 + +## 範例 + +### 向未認證使用者顯示登入 UI + +您可以使用 [`unauthorized`](/docs/app/api-reference/functions/unauthorized) 函式來渲染帶有登入 UI 的 `unauthorized.js` 檔案。 + +```tsx filename="app/dashboard/page.tsx" switcher +import { verifySession } from '@/app/lib/dal' +import { unauthorized } from 'next/navigation' + +export default async function DashboardPage() { + const session = await verifySession() + + if (!session) { + unauthorized() + } + + return
Dashboard
+} +``` + +```jsx filename="app/dashboard/page.js" switcher +import { verifySession } from '@/app/lib/dal' +import { unauthorized } from 'next/navigation' + +export default async function DashboardPage() { + const session = await verifySession() + + if (!session) { + unauthorized() + } + + return
Dashboard
+} +``` + +```tsx filename="app/unauthorized.tsx" switcher +import Login from '@/app/components/Login' + +export default function UnauthorizedPage() { + return ( +
+

401 - Unauthorized

+

Please log in to access this page.

+ +
+ ) +} +``` + +```jsx filename="app/unauthorized.js" switcher +import Login from '@/app/components/Login' + +export default function UnauthorizedPage() { + return ( +
+

401 - Unauthorized

+

Please log in to access this page.

+ +
+ ) +} +``` + +## 版本歷史 + +| 版本 | 變更 | +| ---------- | ----------------------------- | +| `v15.1.0` | 新增 `unauthorized.js` 功能。 | \ No newline at end of file diff --git a/apps/docs/content/zh-hant/docs/01-app/05-api-reference/04-functions/after.mdx b/apps/docs/content/zh-hant/docs/01-app/03-api-reference/04-functions/after.mdx similarity index 100% rename from apps/docs/content/zh-hant/docs/01-app/05-api-reference/04-functions/after.mdx rename to apps/docs/content/zh-hant/docs/01-app/03-api-reference/04-functions/after.mdx diff --git a/apps/docs/content/zh-hant/docs/01-app/05-api-reference/04-functions/cacheLife.mdx b/apps/docs/content/zh-hant/docs/01-app/03-api-reference/04-functions/cacheLife.mdx similarity index 100% rename from apps/docs/content/zh-hant/docs/01-app/05-api-reference/04-functions/cacheLife.mdx rename to apps/docs/content/zh-hant/docs/01-app/03-api-reference/04-functions/cacheLife.mdx diff --git a/apps/docs/content/zh-hant/docs/01-app/05-api-reference/04-functions/cacheTag.mdx b/apps/docs/content/zh-hant/docs/01-app/03-api-reference/04-functions/cacheTag.mdx similarity index 100% rename from apps/docs/content/zh-hant/docs/01-app/05-api-reference/04-functions/cacheTag.mdx rename to apps/docs/content/zh-hant/docs/01-app/03-api-reference/04-functions/cacheTag.mdx diff --git a/apps/docs/content/zh-hant/docs/01-app/03-api-reference/04-functions/connection.mdx b/apps/docs/content/zh-hant/docs/01-app/03-api-reference/04-functions/connection.mdx new file mode 100644 index 00000000..5e1d2aea --- /dev/null +++ b/apps/docs/content/zh-hant/docs/01-app/03-api-reference/04-functions/connection.mdx @@ -0,0 +1,60 @@ +--- +source-updated-at: 2025-08-09T22:43:46.028Z +translation-updated-at: 2025-08-09T22:43:46.028Z +title: connection +description: 關於 `connection` 函式的 API 參考文件。 +--- + +`connection()` 函式允許您指定渲染應等待使用者請求後再繼續執行。 + +當元件不使用[動態 API](/docs/app/getting-started/partial-prerendering#dynamic-rendering),但您希望它在執行階段動態渲染而非在建置階段靜態渲染時,此函式特別有用。這種情況通常發生在您存取外部資訊且有意改變渲染結果時,例如使用 `Math.random()` 或 `new Date()`。 + +```ts filename="app/page.tsx" switcher +import { connection } from 'next/server' + +export default async function Page() { + await connection() + // 以下內容將被排除在預先渲染之外 + const rand = Math.random() + return {rand} +} +``` + +```jsx filename="app/page.js" switcher +import { connection } from 'next/server' + +export default async function Page() { + await connection() + // 以下內容將被排除在預先渲染之外 + const rand = Math.random() + return {rand} +} +``` + +## 參考 + +### 類型 + +```jsx +function connection(): Promise +``` + +### 參數 + +- 此函式不接受任何參數。 + +### 回傳值 + +- 此函式回傳一個 `void` Promise,不應被消費使用。 + +## 須知事項 + +- `connection` 取代了 [`unstable_noStore`](/docs/app/api-reference/functions/unstable_noStore),以更好地與 Next.js 的未來發展方向保持一致。 +- 僅在需要動態渲染且未使用常見動態 API 時才需使用此函式。 + +### 版本歷史 + +| 版本 | 變更內容 | +| ------------- | ------------------------- | +| `v15.0.0` | `connection` 穩定化。 | +| `v15.0.0-RC` | 首次引入 `connection`。 | \ No newline at end of file diff --git a/apps/docs/content/zh-hant/docs/01-app/05-api-reference/04-functions/cookies.mdx b/apps/docs/content/zh-hant/docs/01-app/03-api-reference/04-functions/cookies.mdx similarity index 100% rename from apps/docs/content/zh-hant/docs/01-app/05-api-reference/04-functions/cookies.mdx rename to apps/docs/content/zh-hant/docs/01-app/03-api-reference/04-functions/cookies.mdx diff --git a/apps/docs/content/zh-hant/docs/01-app/05-api-reference/04-functions/draft-mode.mdx b/apps/docs/content/zh-hant/docs/01-app/03-api-reference/04-functions/draft-mode.mdx similarity index 100% rename from apps/docs/content/zh-hant/docs/01-app/05-api-reference/04-functions/draft-mode.mdx rename to apps/docs/content/zh-hant/docs/01-app/03-api-reference/04-functions/draft-mode.mdx diff --git a/apps/docs/content/zh-hant/docs/01-app/05-api-reference/04-functions/fetch.mdx b/apps/docs/content/zh-hant/docs/01-app/03-api-reference/04-functions/fetch.mdx similarity index 100% rename from apps/docs/content/zh-hant/docs/01-app/05-api-reference/04-functions/fetch.mdx rename to apps/docs/content/zh-hant/docs/01-app/03-api-reference/04-functions/fetch.mdx diff --git a/apps/docs/content/zh-hant/docs/01-app/05-api-reference/04-functions/forbidden.mdx b/apps/docs/content/zh-hant/docs/01-app/03-api-reference/04-functions/forbidden.mdx similarity index 100% rename from apps/docs/content/zh-hant/docs/01-app/05-api-reference/04-functions/forbidden.mdx rename to apps/docs/content/zh-hant/docs/01-app/03-api-reference/04-functions/forbidden.mdx diff --git a/apps/docs/content/zh-hant/docs/01-app/03-api-reference/04-functions/generate-image-metadata.mdx b/apps/docs/content/zh-hant/docs/01-app/03-api-reference/04-functions/generate-image-metadata.mdx new file mode 100644 index 00000000..22210e42 --- /dev/null +++ b/apps/docs/content/zh-hant/docs/01-app/03-api-reference/04-functions/generate-image-metadata.mdx @@ -0,0 +1,228 @@ +--- +source-updated-at: 2025-08-09T22:43:46.028Z +translation-updated-at: 2025-08-09T22:43:46.028Z +title: generateImageMetadata +description: 了解如何在單一 Metadata API 特殊檔案中生成多張圖片。 +related: + title: 後續步驟 + description: 查看所有 Metadata API 選項。 + links: + - app/api-reference/file-conventions/metadata +--- + +您可以使用 `generateImageMetadata` 來生成同一圖片的多個版本,或為一個路由區段返回多張圖片。這在您希望避免硬編碼元數據值時非常有用,例如圖示。 + +## 參數 + +`generateImageMetadata` 函數接受以下參數: + +#### `params` (選填) + +一個物件,包含從根區段到呼叫 `generateImageMetadata` 的區段的[動態路由參數](/docs/app/api-reference/file-conventions/dynamic-routes)物件。 + +```tsx filename="icon.tsx" switcher +export function generateImageMetadata({ + params, +}: { + params: { slug: string } +}) { + // ... +} +``` + +```jsx filename="icon.js" switcher +export function generateImageMetadata({ params }) { + // ... +} +``` + +| 路由 | URL | `params` | +| ------------------------------- | ----------- | ------------------------- | +| `app/shop/icon.js` | `/shop` | `undefined` | +| `app/shop/[slug]/icon.js` | `/shop/1` | `{ slug: '1' }` | +| `app/shop/[tag]/[item]/icon.js` | `/shop/1/2` | `{ tag: '1', item: '2' }` | + +## 返回值 + +`generateImageMetadata` 函數應返回一個物件陣列,包含圖片的元數據,如 `alt` 和 `size`。此外,每個項目**必須**包含一個 `id` 值,該值將傳遞給圖片生成函數的 props。 + +| 圖片元數據物件 | 類型 | +| --------------------- | ----------------------------------- | +| `id` | `string` (必填) | +| `alt` | `string` | +| `size` | `{ width: number; height: number }` | +| `contentType` | `string` | + +```tsx filename="icon.tsx" switcher +import { ImageResponse } from 'next/og' + +export function generateImageMetadata() { + return [ + { + contentType: 'image/png', + size: { width: 48, height: 48 }, + id: 'small', + }, + { + contentType: 'image/png', + size: { width: 72, height: 72 }, + id: 'medium', + }, + ] +} + +export default function Icon({ id }: { id: string }) { + return new ImageResponse( + ( +
+ Icon {id} +
+ ) + ) +} +``` + +```jsx filename="icon.js" switcher +import { ImageResponse } from 'next/og' + +export function generateImageMetadata() { + return [ + { + contentType: 'image/png', + size: { width: 48, height: 48 }, + id: 'small', + }, + { + contentType: 'image/png', + size: { width: 72, height: 72 }, + id: 'medium', + }, + ] +} + +export default function Icon({ id }) { + return new ImageResponse( + ( +
+ Icon {id} +
+ ) + ) +} +``` + +### 範例 + +#### 使用外部數據 + +此範例使用 `params` 物件和外部數據為路由區段生成多張 [Open Graph 圖片](/docs/app/api-reference/file-conventions/metadata/opengraph-image)。 + +```tsx filename="app/products/[id]/opengraph-image.tsx" switcher +import { ImageResponse } from 'next/og' +import { getCaptionForImage, getOGImages } from '@/app/utils/images' + +export async function generateImageMetadata({ + params, +}: { + params: { id: string } +}) { + const images = await getOGImages(params.id) + + return images.map((image, idx) => ({ + id: idx, + size: { width: 1200, height: 600 }, + alt: image.text, + contentType: 'image/png', + })) +} + +export default async function Image({ + params, + id, +}: { + params: { id: string } + id: number +}) { + const productId = (await params).id + const imageId = id + const text = await getCaptionForImage(productId, imageId) + + return new ImageResponse( + ( +
+ {text} +
+ ) + ) +} +``` + +```jsx filename="app/products/[id]/opengraph-image.js" switcher +import { ImageResponse } from 'next/og' +import { getCaptionForImage, getOGImages } from '@/app/utils/images' + +export async function generateImageMetadata({ params }) { + const images = await getOGImages(params.id) + + return images.map((image, idx) => ({ + id: idx, + size: { width: 1200, height: 600 }, + alt: image.text, + contentType: 'image/png', + })) +} + +export default async function Image({ params, id }) { + const productId = (await params).id + const imageId = id + const text = await getCaptionForImage(productId, imageId) + + return new ImageResponse( + ( +
+ {text} +
+ ) + ) +} +``` + +## 版本歷史 + +| 版本 | 變更 | +| --------- | ----------------------------------- | +| `v13.3.0` | 引入 `generateImageMetadata`。 | \ No newline at end of file diff --git a/apps/docs/content/zh-hant/docs/01-app/05-api-reference/04-functions/generate-metadata.mdx b/apps/docs/content/zh-hant/docs/01-app/03-api-reference/04-functions/generate-metadata.mdx similarity index 100% rename from apps/docs/content/zh-hant/docs/01-app/05-api-reference/04-functions/generate-metadata.mdx rename to apps/docs/content/zh-hant/docs/01-app/03-api-reference/04-functions/generate-metadata.mdx diff --git a/apps/docs/content/zh-hant/docs/01-app/03-api-reference/04-functions/generate-sitemaps.mdx b/apps/docs/content/zh-hant/docs/01-app/03-api-reference/04-functions/generate-sitemaps.mdx new file mode 100644 index 00000000..aa2b338a --- /dev/null +++ b/apps/docs/content/zh-hant/docs/01-app/03-api-reference/04-functions/generate-sitemaps.mdx @@ -0,0 +1,81 @@ +--- +source-updated-at: 2025-08-09T22:43:46.028Z +translation-updated-at: 2025-08-09T22:43:46.028Z +title: generateSitemaps +nav_title: generateSitemaps +description: 了解如何使用 generateSiteMaps 函式為您的應用程式建立多個網站地圖 (sitemap)。 +related: + title: 後續步驟 + description: 了解如何為您的 Next.js 應用程式建立網站地圖 (sitemap)。 + links: + - app/api-reference/file-conventions/metadata/sitemap +--- + +您可以使用 `generateSitemaps` 函式為您的應用程式產生多個網站地圖 (sitemap)。 + +## 回傳值 + +`generateSitemaps` 會回傳一個包含 `id` 屬性的物件陣列。 + +## 網址 + +您產生的網站地圖將會位於 `/.../sitemap/[id].xml`。例如 `/product/sitemap/1.xml`。 + +## 範例 + +舉例來說,若要使用 `generateSitemaps` 分割網站地圖,請回傳一個包含網站地圖 `id` 的物件陣列。然後使用 `id` 來產生獨立的網站地圖。 + +```ts filename="app/product/sitemap.ts" switcher +import { BASE_URL } from '@/app/lib/constants' + +export async function generateSitemaps() { + // 取得產品總數並計算需要的網站地圖數量 + return [{ id: 0 }, { id: 1 }, { id: 2 }, { id: 3 }] +} + +export default async function sitemap({ + id, +}: { + id: number +}): Promise { + // Google 的限制是每個網站地圖 50,000 個網址 + const start = id * 50000 + const end = start + 50000 + const products = await getProducts( + `SELECT id, date FROM products WHERE id BETWEEN ${start} AND ${end}` + ) + return products.map((product) => ({ + url: `${BASE_URL}/product/${product.id}`, + lastModified: product.date, + })) +} +``` + +```js filename="app/product/sitemap.js" switcher +import { BASE_URL } from '@/app/lib/constants' + +export async function generateSitemaps() { + // 取得產品總數並計算需要的網站地圖數量 + return [{ id: 0 }, { id: 1 }, { id: 2 }, { id: 3 }] +} + +export default async function sitemap({ id }) { + // Google 的限制是每個網站地圖 50,000 個網址 + const start = id * 50000 + const end = start + 50000 + const products = await getProducts( + `SELECT id, date FROM products WHERE id BETWEEN ${start} AND ${end}` + ) + return products.map((product) => ({ + url: `${BASE_URL}/product/${id}`, + lastModified: product.date, + })) +} +``` + +## 版本歷史 + +| 版本 | 變更內容 | +| ---------- | ---------------------------------------------------------------------------------------------------------------------------------------- | +| `v15.0.0` | `generateSitemaps` 現在會在開發環境和生產環境產生一致的網址 | +| `v13.3.2` | `generateSitemaps` 功能推出。在開發環境中,您可以在 `/.../sitemap.xml/[id]` 查看產生的網站地圖。例如 `/product/sitemap.xml/1`。 | \ No newline at end of file diff --git a/apps/docs/content/zh-hant/docs/01-app/05-api-reference/04-functions/generate-static-params.mdx b/apps/docs/content/zh-hant/docs/01-app/03-api-reference/04-functions/generate-static-params.mdx similarity index 100% rename from apps/docs/content/zh-hant/docs/01-app/05-api-reference/04-functions/generate-static-params.mdx rename to apps/docs/content/zh-hant/docs/01-app/03-api-reference/04-functions/generate-static-params.mdx diff --git a/apps/docs/content/zh-hant/docs/01-app/03-api-reference/04-functions/generate-viewport.mdx b/apps/docs/content/zh-hant/docs/01-app/03-api-reference/04-functions/generate-viewport.mdx new file mode 100644 index 00000000..43fd98ff --- /dev/null +++ b/apps/docs/content/zh-hant/docs/01-app/03-api-reference/04-functions/generate-viewport.mdx @@ -0,0 +1,239 @@ +--- +source-updated-at: 2025-08-09T22:43:46.028Z +translation-updated-at: 2025-08-09T22:43:46.028Z +title: generateViewport +description: 關於 `generateViewport` 函式的 API 參考文件。 +related: + title: 後續步驟 + description: 查看所有 Metadata API 選項。 + links: + - app/api-reference/file-conventions/metadata +--- + +您可以使用靜態的 `viewport` 物件或動態的 `generateViewport` 函式來自訂頁面的初始視窗設定。 + +> **須知事項**: +> +> - `viewport` 物件和 `generateViewport` 函式匯出 **僅在伺服器元件 (Server Components) 中支援**。 +> - 您無法從同一個路由區段同時匯出 `viewport` 物件和 `generateViewport` 函式。 +> - 如果您正在從遷移 `metadata` 匯出,可以使用 [metadata-to-viewport-export codemod](/docs/app/guides/upgrading/codemods#metadata-to-viewport-export) 來更新您的變更。 + +## `viewport` 物件 + +要定義視窗選項,請從 `layout.jsx` 或 `page.jsx` 檔案匯出 `viewport` 物件。 + +```tsx filename="layout.tsx | page.tsx" switcher +import type { Viewport } from 'next' + +export const viewport: Viewport = { + themeColor: 'black', +} + +export default function Page() {} +``` + +```jsx filename="layout.jsx | page.jsx" switcher +export const viewport = { + themeColor: 'black', +} + +export default function Page() {} +``` + +## `generateViewport` 函式 + +`generateViewport` 應返回一個包含一個或多個視窗欄位的 [`Viewport` 物件](#viewport-fields)。 + +```tsx filename="layout.tsx | page.tsx" switcher +export function generateViewport({ params }) { + return { + themeColor: '...', + } +} +``` + +```jsx filename="layout.js | page.js" switcher +export function generateViewport({ params }) { + return { + themeColor: '...', + } +} +``` + +> **須知事項**: +> +> - 如果視窗設定不依賴於執行時資訊,應使用靜態的 [`viewport` 物件](#the-viewport-object) 而非 `generateViewport` 來定義。 + +## 視窗欄位 + +### `themeColor` + +了解更多關於 [`theme-color`](https://developer.mozilla.org/docs/Web/HTML/Element/meta/name/theme-color) 的資訊。 + +**簡單主題色** + +```tsx filename="layout.tsx | page.tsx" switcher +import type { Viewport } from 'next' + +export const viewport: Viewport = { + themeColor: 'black', +} +``` + +```jsx filename="layout.jsx | page.jsx" switcher +export const viewport = { + themeColor: 'black', +} +``` + +```html filename=" output" hideLineNumbers + +``` + +**帶有 media 屬性** + +```tsx filename="layout.tsx | page.tsx" switcher +import type { Viewport } from 'next' + +export const viewport: Viewport = { + themeColor: [ + { media: '(prefers-color-scheme: light)', color: 'cyan' }, + { media: '(prefers-color-scheme: dark)', color: 'black' }, + ], +} +``` + +```jsx filename="layout.jsx | page.jsx" switcher +export const viewport = { + themeColor: [ + { media: '(prefers-color-scheme: light)', color: 'cyan' }, + { media: '(prefers-color-scheme: dark)', color: 'black' }, + ], +} +``` + +```html filename=" output" hideLineNumbers + + +``` + +### `width`, `initialScale`, `maximumScale` 和 `userScalable` + +> **須知事項**: `viewport` meta 標籤會自動設定,通常不需要手動配置,因為預設值已經足夠。但為了完整性,仍提供相關資訊。 + +```tsx filename="layout.tsx | page.tsx" switcher +import type { Viewport } from 'next' + +export const viewport: Viewport = { + width: 'device-width', + initialScale: 1, + maximumScale: 1, + userScalable: false, + // 也支援但不常用 + // interactiveWidget: 'resizes-visual', +} +``` + +```jsx filename="layout.jsx | page.jsx" switcher +export const viewport = { + width: 'device-width', + initialScale: 1, + maximumScale: 1, + userScalable: false, + // 也支援但不常用 + // interactiveWidget: 'resizes-visual', +} +``` + +```html filename=" output" hideLineNumbers + +``` + +### `colorScheme` + +了解更多關於 [`color-scheme`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/meta/name#:~:text=color%2Dscheme%3A%20specifies,of%20the%20following%3A) 的資訊。 + +```tsx filename="layout.tsx | page.tsx" switcher +import type { Viewport } from 'next' + +export const viewport: Viewport = { + colorScheme: 'dark', +} +``` + +```jsx filename="layout.jsx | page.jsx" switcher +export const viewport = { + colorScheme: 'dark', +} +``` + +```html filename=" output" hideLineNumbers + +``` + +## 型別 + +您可以透過使用 `Viewport` 型別來為您的視窗物件增加型別安全性。如果您在 IDE 中使用 [內建的 TypeScript 外掛](/docs/app/api-reference/config/typescript),則不需要手動新增型別,但仍可以明確新增。 + +### `viewport` 物件 + +```tsx +import type { Viewport } from 'next' + +export const viewport: Viewport = { + themeColor: 'black', +} +``` + +### `generateViewport` 函式 + +#### 常規函式 + +```tsx +import type { Viewport } from 'next' + +export function generateViewport(): Viewport { + return { + themeColor: 'black', + } +} +``` + +#### 帶有區段屬性 + +```tsx +import type { Viewport } from 'next' + +type Props = { + params: Promise<{ id: string }> + searchParams: Promise<{ [key: string]: string | string[] | undefined }> +} + +export function generateViewport({ params, searchParams }: Props): Viewport { + return { + themeColor: 'black', + } +} + +export default function Page({ params, searchParams }: Props) {} +``` + +#### JavaScript 專案 + +對於 JavaScript 專案,可以使用 JSDoc 來增加型別安全性。 + +```js +/** @type {import("next").Viewport} */ +export const viewport = { + themeColor: 'black', +} +``` + +## 版本歷史 + +| 版本 | 變更 | +| ---------- | ----------------------------------------- | +| `v14.0.0` | 引入 `viewport` 和 `generateViewport`。 | \ No newline at end of file diff --git a/apps/docs/content/zh-hant/docs/01-app/03-api-reference/04-functions/headers.mdx b/apps/docs/content/zh-hant/docs/01-app/03-api-reference/04-functions/headers.mdx new file mode 100644 index 00000000..df9de87a --- /dev/null +++ b/apps/docs/content/zh-hant/docs/01-app/03-api-reference/04-functions/headers.mdx @@ -0,0 +1,75 @@ +--- +source-updated-at: 2025-08-09T22:43:46.028Z +translation-updated-at: 2025-08-09T22:43:46.028Z +title: headers +description: 關於 `headers` 函式的 API 參考文件。 +--- + +`headers` 是一個**非同步**函式,可讓您從[伺服器元件 (Server Component)](/docs/app/getting-started/server-and-client-components) **讀取** HTTP 傳入請求的標頭。 + +```tsx filename="app/page.tsx" switcher +import { headers } from 'next/headers' + +export default async function Page() { + const headersList = await headers() + const userAgent = headersList.get('user-agent') +} +``` + +```jsx filename="app/page.js" switcher +import { headers } from 'next/headers' + +export default async function Page() { + const headersList = await headers() + const userAgent = headersList.get('user-agent') +} +``` + +## 參考 + +### 參數 + +`headers` 不接受任何參數。 + +### 回傳值 + +`headers` 回傳一個**唯讀**的 [Web Headers](https://developer.mozilla.org/docs/Web/API/Headers) 物件。 + +- [`Headers.entries()`](https://developer.mozilla.org/docs/Web/API/Headers/entries): 回傳一個 [`iterator`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Iteration_protocols),允許遍歷此物件中包含的所有鍵/值對。 +- [`Headers.forEach()`](https://developer.mozilla.org/docs/Web/API/Headers/forEach): 對此 `Headers` 物件中的每個鍵/值對執行一次提供的函式。 +- [`Headers.get()`](https://developer.mozilla.org/docs/Web/API/Headers/get): 回傳一個 [`String`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) 序列,包含 `Headers` 物件中指定名稱標頭的所有值。 +- [`Headers.has()`](https://developer.mozilla.org/docs/Web/API/Headers/has): 回傳一個布林值,表示 `Headers` 物件是否包含特定標頭。 +- [`Headers.keys()`](https://developer.mozilla.org/docs/Web/API/Headers/keys): 回傳一個 [`iterator`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Iteration_protocols),允許遍歷此物件中包含的所有鍵。 +- [`Headers.values()`](https://developer.mozilla.org/docs/Web/API/Headers/values): 回傳一個 [`iterator`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Iteration_protocols),允許遍歷此物件中包含的所有值。 + +## 須知事項 + +- `headers` 是一個**非同步**函式,會回傳一個 promise。您必須使用 `async/await` 或 React 的 [`use`](https://react.dev/reference/react/use) 函式。 + - 在版本 14 及更早之前,`headers` 是一個同步函式。為了向後兼容,您仍可在 Next.js 15 中以同步方式存取它,但此行為將在未來被棄用。 +- 由於 `headers` 是唯讀的,您無法 `set` 或 `delete` 傳出請求的標頭。 +- `headers` 是一個[動態 API (Dynamic API)](/docs/app/getting-started/partial-prerendering#dynamic-rendering#dynamic-apis),其回傳值無法預先得知。使用它會使路由選擇**[動態渲染 (dynamic rendering)](/docs/app/getting-started/partial-prerendering#dynamic-rendering)**。 + +## 範例 + +### 使用 Authorization 標頭 + +```jsx filename="app/page.js" +import { headers } from 'next/headers' + +export default async function Page() { + const authorization = (await headers()).get('authorization') + const res = await fetch('...', { + headers: { authorization }, // 轉發 authorization 標頭 + }) + const user = await res.json() + + return

{user.name}

+} +``` + +## 版本歷史 + +| 版本 | 變更 | +| ------------- | -------------------------------------------------------------------------------------------------- | +| `v15.0.0-RC` | `headers` 現在是一個非同步函式。提供了一個 [codemod](/docs/app/guides/upgrading/codemods#150) 供使用。 | +| `v13.0.0` | 引入 `headers`。 | \ No newline at end of file diff --git a/apps/docs/content/zh-hant/docs/01-app/03-api-reference/04-functions/image-response.mdx b/apps/docs/content/zh-hant/docs/01-app/03-api-reference/04-functions/image-response.mdx new file mode 100644 index 00000000..5408d51f --- /dev/null +++ b/apps/docs/content/zh-hant/docs/01-app/03-api-reference/04-functions/image-response.mdx @@ -0,0 +1,214 @@ +--- +source-updated-at: 2025-08-09T22:43:46.028Z +translation-updated-at: 2025-08-09T22:43:46.028Z +title: ImageResponse +description: 關於 `ImageResponse` 建構子的 API 參考文件。 +--- + +`ImageResponse` 建構子允許你使用 JSX 和 CSS 來生成動態圖片。這對於生成社群媒體圖片(如 Open Graph 圖片、Twitter 卡片等)非常有用。 + +## 參考 + +### 參數 + +`ImageResponse` 可使用以下參數: + +```jsx +import { ImageResponse } from 'next/og' + +new ImageResponse( + element: ReactElement, + options: { + width?: number = 1200 + height?: number = 630 + emoji?: 'twemoji' | 'blobmoji' | 'noto' | 'openmoji' = 'twemoji', + fonts?: { + name: string, + data: ArrayBuffer, + weight: number, + style: 'normal' | 'italic' + }[] + debug?: boolean = false + + // 將傳遞給 HTTP 回應的選項 + status?: number = 200 + statusText?: string + headers?: Record + }, +) +``` + +> 範例可在 [Vercel OG Playground](https://og-playground.vercel.app/) 中找到。 + +### 支援的 HTML 和 CSS 功能 + +`ImageResponse` 支援常見的 CSS 屬性,包括 flexbox 和絕對定位、自訂字體、文字換行、置中以及嵌套圖片。 + +請參考 [Satori 的文件](https://github.com/vercel/satori#css) 以查看支援的 HTML 和 CSS 功能清單。 + +## 行為 + +- `ImageResponse` 使用 [@vercel/og](https://vercel.com/docs/concepts/functions/edge-functions/og-image-generation)、[Satori](https://github.com/vercel/satori) 和 Resvg 將 HTML 和 CSS 轉換為 PNG。 +- 僅支援 flexbox 和部分 CSS 屬性。進階佈局(例如 `display: grid`)無法使用。 +- 最大套件大小為 `500KB`。套件大小包括你的 JSX、CSS、字體、圖片和其他任何資源。如果超過限制,請考慮減少資源大小或在執行時獲取。 +- 僅支援 `ttf`、`otf` 和 `woff` 字體格式。為了最大化字體解析速度,`ttf` 或 `otf` 比 `woff` 更推薦。 + +## 範例 + +### 路由處理器 + +`ImageResponse` 可用於路由處理器中,以在請求時動態生成圖片。 + +```js filename="app/api/route.js" +import { ImageResponse } from 'next/og' + +export async function GET() { + try { + return new ImageResponse( + ( +
+
+ Welcome to My Site +
+
+ Generated with Next.js ImageResponse +
+
+ ), + { + width: 1200, + height: 630, + } + ) + } catch (e) { + console.log(`${e.message}`) + return new Response(`Failed to generate the image`, { + status: 500, + }) + } +} +``` + +### 基於檔案的元數據 + +你可以在 [`opengraph-image.tsx`](/docs/app/api-reference/file-conventions/metadata/opengraph-image) 檔案中使用 `ImageResponse`,以在構建時或請求時動態生成 Open Graph 圖片。 + +```tsx filename="app/opengraph-image.tsx" +import { ImageResponse } from 'next/og' + +// 圖片元數據 +export const alt = 'My site' +export const size = { + width: 1200, + height: 630, +} + +export const contentType = 'image/png' + +// 圖片生成 +export default async function Image() { + return new ImageResponse( + ( + // ImageResponse JSX 元素 +
+ My site +
+ ), + // ImageResponse 選項 + { + // 為方便起見,我們可以重複使用匯出的 opengraph-image + // 大小配置來設定 ImageResponse 的寬度和高度。 + ...size, + } + ) +} +``` + +### 自訂字體 + +你可以通過在選項中提供 `fonts` 陣列來在 `ImageResponse` 中使用自訂字體。 + +```tsx filename="app/opengraph-image.tsx" +import { ImageResponse } from 'next/og' +import { readFile } from 'node:fs/promises' +import { join } from 'node:path' + +// 圖片元數據 +export const alt = 'My site' +export const size = { + width: 1200, + height: 630, +} + +export const contentType = 'image/png' + +// 圖片生成 +export default async function Image() { + // 字體載入,process.cwd() 是 Next.js 專案目錄 + const interSemiBold = await readFile( + join(process.cwd(), 'assets/Inter-SemiBold.ttf') + ) + + return new ImageResponse( + ( + // ... + ), + // ImageResponse 選項 + { + // 為方便起見,我們可以重複使用匯出的 opengraph-image + // 大小配置來設定 ImageResponse 的寬度和高度。 + ...size, + fonts: [ + { + name: 'Inter', + data: interSemiBold, + style: 'normal', + weight: 400, + }, + ], + } + ) +} +``` + +## 版本歷史 + +| 版本 | 變更 | +| ---------- | ------------------------------------------------- | +| `v14.0.0` | `ImageResponse` 從 `next/server` 移至 `next/og` | +| `v13.3.0` | `ImageResponse` 可從 `next/server` 匯入。 | +| `v13.0.0` | `ImageResponse` 通過 `@vercel/og` 套件引入。 | \ No newline at end of file diff --git a/apps/docs/content/zh-hant/docs/01-app/03-api-reference/04-functions/index.mdx b/apps/docs/content/zh-hant/docs/01-app/03-api-reference/04-functions/index.mdx new file mode 100644 index 00000000..c2078b3a --- /dev/null +++ b/apps/docs/content/zh-hant/docs/01-app/03-api-reference/04-functions/index.mdx @@ -0,0 +1,8 @@ +--- +source-updated-at: 2025-08-09T22:43:46.028Z +translation-updated-at: 2025-08-09T22:43:46.028Z +title: 函式 +description: Next.js 函式與鉤子 (Hooks) 的 API 參考文件。 +--- + +{/* 此文件內容同時適用於 app 和 pages 路由。您可以使用 `內容` 元件來新增專屬於 Pages Router 的內容。任何共用內容都不應被包裹在元件中。 */} \ No newline at end of file diff --git a/apps/docs/content/zh-hant/docs/01-app/03-api-reference/04-functions/next-request.mdx b/apps/docs/content/zh-hant/docs/01-app/03-api-reference/04-functions/next-request.mdx new file mode 100644 index 00000000..bc25d834 --- /dev/null +++ b/apps/docs/content/zh-hant/docs/01-app/03-api-reference/04-functions/next-request.mdx @@ -0,0 +1,125 @@ +--- +source-updated-at: 2025-08-09T22:43:46.028Z +translation-updated-at: 2025-08-09T22:43:46.028Z +title: NextRequest +description: NextRequest 的 API 參考文檔。 +--- + +{/* 此文件內容在應用程式路由器和頁面路由器之間共享。您可以使用 `內容` 元件來新增僅適用於頁面路由器的內容。任何共享內容不應包裹在元件中。 */} + +NextRequest 擴展了 [Web Request API](https://developer.mozilla.org/docs/Web/API/Request),並提供了額外的便利方法。 + +## `cookies` + +讀取或修改請求中的 [`Set-Cookie`](https://developer.mozilla.org/docs/Web/HTTP/Headers/Set-Cookie) 標頭。 + +### `set(name, value)` + +根據給定的名稱,在請求中設定一個具有指定值的 cookie。 + +```ts +// 假設收到 /home 的請求 +// 設定一個 cookie 來隱藏橫幅 +// 請求將包含 `Set-Cookie:show-banner=false;path=/home` 標頭 +request.cookies.set('show-banner', 'false') +``` + +### `get(name)` + +根據 cookie 名稱,返回該 cookie 的值。如果找不到 cookie,則返回 `undefined`。如果找到多個 cookie,則返回第一個。 + +```ts +// 假設收到 /home 的請求 +// { name: 'show-banner', value: 'false', Path: '/home' } +request.cookies.get('show-banner') +``` + +### `getAll()` + +根據 cookie 名稱,返回該 cookie 的所有值。如果未提供名稱,則返回請求中的所有 cookie。 + +```ts +// 假設收到 /home 的請求 +// [ +// { name: 'experiments', value: 'new-pricing-page', Path: '/home' }, +// { name: 'experiments', value: 'winter-launch', Path: '/home' }, +// ] +request.cookies.getAll('experiments') +// 或者,取得請求中的所有 cookie +request.cookies.getAll() +``` + +### `delete(name)` + +根據 cookie 名稱,從請求中刪除該 cookie。 + +```ts +// 如果刪除成功返回 true,如果沒有刪除任何內容則返回 false +request.cookies.delete('experiments') +``` + +### `has(name)` + +根據 cookie 名稱,如果請求中存在該 cookie,則返回 `true`。 + +```ts +// 如果 cookie 存在返回 true,否則返回 false +request.cookies.has('experiments') +``` + +### `clear()` + +從請求中移除 `Set-Cookie` 標頭。 + +```ts +request.cookies.clear() +``` + +## `nextUrl` + +擴展了原生的 [`URL`](https://developer.mozilla.org/docs/Web/API/URL) API,並提供了額外的便利方法,包括 Next.js 特有的屬性。 + +```ts +// 假設收到 /home 的請求,pathname 為 /home +request.nextUrl.pathname +// 假設收到 /home?name=lee 的請求,searchParams 為 { 'name': 'lee' } +request.nextUrl.searchParams +``` + +以下是可用的選項: + + + +| 屬性 | 類型 | 描述 | +| ---------------- | ------------------------- | ------------------------------------------------------------------------------------------------------------------------------ | +| `basePath` | `string` | URL 的 [基礎路徑](/docs/pages/api-reference/config/next-config-js/basePath)。 | +| `buildId` | `string` \| `undefined` | Next.js 應用程式的建置識別碼。可 [自訂](/docs/pages/api-reference/config/next-config-js/generateBuildId)。 | +| `defaultLocale` | `string` \| `undefined` | [國際化](/docs/pages/guides/internationalization) 的預設語言設定。 | +| `domainLocale` | | | +| - `defaultLocale` | `string` | 網域內的預設語言設定。 | +| - `domain` | `string` | 與特定語言設定關聯的網域。 | +| - `http` | `boolean` \| `undefined` | 表示網域是否使用 HTTP。 | +| `locales` | `string[]` \| `undefined` | 可用的語言設定陣列。 | +| `locale` | `string` \| `undefined` | 當前使用的語言設定。 | +| `url` | `URL` | URL 物件。 | + + + + + +| 屬性 | 類型 | 描述 | +| ------------- | ----------------------- | ---------------------------------------------------------------------------------------------------------------------------- | +| `basePath` | `string` | URL 的 [基礎路徑](/docs/app/api-reference/config/next-config-js/basePath)。 | +| `buildId` | `string` \| `undefined` | Next.js 應用程式的建置識別碼。可 [自訂](/docs/app/api-reference/config/next-config-js/generateBuildId)。 | +| `pathname` | `string` | URL 的路徑名稱。 | +| `searchParams` | `Object` | URL 的查詢參數。 | + +> **注意:** 頁面路由器中的國際化屬性不適用於應用程式路由器。了解更多關於 [應用程式路由器的國際化](/docs/app/guides/internationalization)。 + + + +## 版本歷史 + +| 版本 | 變更 | +| ---------- | ------------------------ | +| `v15.0.0` | 移除了 `ip` 和 `geo`。 | \ No newline at end of file diff --git a/apps/docs/content/zh-hant/docs/01-app/03-api-reference/04-functions/next-response.mdx b/apps/docs/content/zh-hant/docs/01-app/03-api-reference/04-functions/next-response.mdx new file mode 100644 index 00000000..83b0bd79 --- /dev/null +++ b/apps/docs/content/zh-hant/docs/01-app/03-api-reference/04-functions/next-response.mdx @@ -0,0 +1,148 @@ +--- +source-updated-at: 2025-08-09T22:43:46.028Z +translation-updated-at: 2025-08-09T22:43:46.028Z +title: NextResponse +description: 關於 NextResponse 的 API 參考文件。 +--- + +{/* 此文件的內容在應用程式路由器和頁面路由器之間共享。您可以使用 `內容` 元件來新增專屬於頁面路由器的內容。任何共享內容都不應包裹在元件中。 */} + +NextResponse 擴展了 [Web Response API](https://developer.mozilla.org/docs/Web/API/Response),並提供了額外的便利方法。 + +## `cookies` + +讀取或修改回應中的 [`Set-Cookie`](https://developer.mozilla.org/docs/Web/HTTP/Headers/Set-Cookie) 標頭。 + +### `set(name, value)` + +根據給定的名稱,在回應中設定一個具有對應值的 cookie。 + +```ts +// 假設傳入的請求是 /home +let response = NextResponse.next() +// 設定一個 cookie 來隱藏橫幅 +response.cookies.set('show-banner', 'false') +// 回應將包含 `Set-Cookie:show-banner=false;path=/home` 標頭 +return response +``` + +### `get(name)` + +根據 cookie 名稱,回傳該 cookie 的值。如果找不到 cookie,則回傳 `undefined`。如果找到多個 cookie,則回傳第一個。 + +```ts +// 假設傳入的請求是 /home +let response = NextResponse.next() +// { name: 'show-banner', value: 'false', Path: '/home' } +response.cookies.get('show-banner') +``` + +### `getAll()` + +根據 cookie 名稱,回傳該 cookie 的所有值。如果未提供名稱,則回傳回應中的所有 cookie。 + +```ts +// 假設傳入的請求是 /home +let response = NextResponse.next() +// [ +// { name: 'experiments', value: 'new-pricing-page', Path: '/home' }, +// { name: 'experiments', value: 'winter-launch', Path: '/home' }, +// ] +response.cookies.getAll('experiments') +// 或者,取得回應中的所有 cookie +response.cookies.getAll() +``` + +### `delete(name)` + +根據 cookie 名稱,從回應中刪除該 cookie。 + +```ts +// 假設傳入的請求是 /home +let response = NextResponse.next() +// 回傳 true 表示已刪除,false 表示未刪除任何內容 +response.cookies.delete('experiments') +``` + +## `json()` + +產生一個包含給定 JSON 主體的回應。 + +```ts filename="app/api/route.ts" switcher +import { NextResponse } from 'next/server' + +export async function GET(request: Request) { + return NextResponse.json({ error: 'Internal Server Error' }, { status: 500 }) +} +``` + +```js filename="app/api/route.js" switcher +import { NextResponse } from 'next/server' + +export async function GET(request) { + return NextResponse.json({ error: 'Internal Server Error' }, { status: 500 }) +} +``` + +## `redirect()` + +產生一個重新導向至指定 [URL](https://developer.mozilla.org/docs/Web/API/URL) 的回應。 + +```ts +import { NextResponse } from 'next/server' + +return NextResponse.redirect(new URL('/new', request.url)) +``` + +[URL](https://developer.mozilla.org/docs/Web/API/URL) 可以在用於 `NextResponse.redirect()` 方法之前被建立和修改。例如,您可以使用 `request.nextUrl` 屬性來取得當前 URL,然後修改它以重新導向至不同的 URL。 + +```ts +import { NextResponse } from 'next/server' + +// 假設有一個傳入的請求... +const loginUrl = new URL('/login', request.url) +// 在 /login URL 上新增 ?from=/incoming-url +loginUrl.searchParams.set('from', request.nextUrl.pathname) +// 然後重新導向至新的 URL +return NextResponse.redirect(loginUrl) +``` + +## `rewrite()` + +產生一個重寫 (代理) 給定 [URL](https://developer.mozilla.org/docs/Web/API/URL) 的回應,同時保留原始 URL。 + +```ts +import { NextResponse } from 'next/server' + +// 傳入的請求: /about, 瀏覽器顯示 /about +// 重寫後的請求: /proxy, 瀏覽器顯示 /about +return NextResponse.rewrite(new URL('/proxy', request.url)) +``` + +## `next()` + +`next()` 方法在中間件中非常有用,因為它允許您提前回傳並繼續路由。 + +```ts +import { NextResponse } from 'next/server' + +return NextResponse.next() +``` + +您也可以在產生回應時轉發 `headers`: + +```ts +import { NextResponse } from 'next/server' + +// 假設有一個傳入的請求... +const newHeaders = new Headers(request.headers) +// 新增一個標頭 +newHeaders.set('x-version', '123') +// 並產生一個包含新標頭的回應 +return NextResponse.next({ + request: { + // 新的請求標頭 + headers: newHeaders, + }, +}) +``` \ No newline at end of file diff --git a/apps/docs/content/zh-hant/docs/01-app/03-api-reference/04-functions/not-found.mdx b/apps/docs/content/zh-hant/docs/01-app/03-api-reference/04-functions/not-found.mdx new file mode 100644 index 00000000..cccae614 --- /dev/null +++ b/apps/docs/content/zh-hant/docs/01-app/03-api-reference/04-functions/not-found.mdx @@ -0,0 +1,41 @@ +--- +source-updated-at: 2025-08-09T22:43:46.028Z +translation-updated-at: 2025-08-09T22:43:46.028Z +title: notFound +description: 關於 `notFound` 函式的 API 參考文件。 +--- + +`notFound` 函式允許您在路由區段內渲染 [`not-found 檔案`](/docs/app/api-reference/file-conventions/not-found),並自動注入 `` 標籤。 + +## `notFound()` + +呼叫 `notFound()` 函式會拋出 `NEXT_HTTP_ERROR_FALLBACK;404` 錯誤,並終止所在路由區段的渲染。透過設定 [**not-found** 檔案](/docs/app/api-reference/file-conventions/not-found),您可以在該區段內優雅地處理此類錯誤,並顯示「找不到頁面」的使用者介面。 + +```jsx filename="app/user/[id]/page.js" +import { notFound } from 'next/navigation' + +async function fetchUser(id) { + const res = await fetch('https://...') + if (!res.ok) return undefined + return res.json() +} + +export default async function Profile({ params }) { + const { id } = await params + const user = await fetchUser(id) + + if (!user) { + notFound() + } + + // ... +} +``` + +> **小知識**:由於使用了 TypeScript 的 [`never`](https://www.typescriptlang.org/docs/handbook/2/functions.html#never) 型別,`notFound()` 不需要使用 `return notFound()` 語法。 + +## 版本歷史 + +| 版本 | 變更內容 | +| ---------- | ---------------------- | +| `v13.0.0` | 新增 `notFound` 功能。 | \ No newline at end of file diff --git a/apps/docs/content/zh-hant/docs/01-app/05-api-reference/04-functions/permanentRedirect.mdx b/apps/docs/content/zh-hant/docs/01-app/03-api-reference/04-functions/permanentRedirect.mdx similarity index 100% rename from apps/docs/content/zh-hant/docs/01-app/05-api-reference/04-functions/permanentRedirect.mdx rename to apps/docs/content/zh-hant/docs/01-app/03-api-reference/04-functions/permanentRedirect.mdx diff --git a/apps/docs/content/zh-hant/docs/01-app/05-api-reference/04-functions/redirect.mdx b/apps/docs/content/zh-hant/docs/01-app/03-api-reference/04-functions/redirect.mdx similarity index 100% rename from apps/docs/content/zh-hant/docs/01-app/05-api-reference/04-functions/redirect.mdx rename to apps/docs/content/zh-hant/docs/01-app/03-api-reference/04-functions/redirect.mdx diff --git a/apps/docs/content/zh-hant/docs/01-app/05-api-reference/04-functions/unauthorized.mdx b/apps/docs/content/zh-hant/docs/01-app/03-api-reference/04-functions/unauthorized.mdx similarity index 100% rename from apps/docs/content/zh-hant/docs/01-app/05-api-reference/04-functions/unauthorized.mdx rename to apps/docs/content/zh-hant/docs/01-app/03-api-reference/04-functions/unauthorized.mdx diff --git a/apps/docs/content/zh-hant/docs/01-app/05-api-reference/04-functions/unstable_cache.mdx b/apps/docs/content/zh-hant/docs/01-app/03-api-reference/04-functions/unstable_cache.mdx similarity index 100% rename from apps/docs/content/zh-hant/docs/01-app/05-api-reference/04-functions/unstable_cache.mdx rename to apps/docs/content/zh-hant/docs/01-app/03-api-reference/04-functions/unstable_cache.mdx diff --git a/apps/docs/content/zh-hant/docs/01-app/03-api-reference/04-functions/unstable_noStore.mdx b/apps/docs/content/zh-hant/docs/01-app/03-api-reference/04-functions/unstable_noStore.mdx new file mode 100644 index 00000000..b6ee8e76 --- /dev/null +++ b/apps/docs/content/zh-hant/docs/01-app/03-api-reference/04-functions/unstable_noStore.mdx @@ -0,0 +1,49 @@ +--- +source-updated-at: 2025-08-09T22:43:46.028Z +translation-updated-at: 2025-08-09T22:43:46.028Z +title: unstable_noStore +description: 關於 `unstable_noStore` 函式的 API 參考文件。 +version: legacy +--- + +**在版本 15 中,我們建議使用 [`connection`](/docs/app/api-reference/functions/connection) 取代 `unstable_noStore`。** + +`unstable_noStore` 可用於宣告式地選擇退出靜態渲染,並表示特定元件不應被快取。 + +```jsx +import { unstable_noStore as noStore } from 'next/cache'; + +export default async function ServerComponent() { + noStore(); + const result = await db.query(...); + ... +} +``` + +> **須知事項**: +> +> - `unstable_noStore` 等同於在 `fetch` 中使用 `cache: 'no-store'` +> - 相較於 `export const dynamic = 'force-dynamic'`,建議優先使用 `unstable_noStore`,因為它更細粒度且能以元件為單位使用 + +- 在 [`unstable_cache`](/docs/app/api-reference/functions/unstable_cache) 內部使用 `unstable_noStore` 並不會退出靜態生成,而是會依據快取配置決定是否快取結果。 + +## 使用方式 + +如果您不想在 `fetch` 中傳遞額外選項(如 `cache: 'no-store'`、`next: { revalidate: 0 }`),或是在無法使用 `fetch` 的情況下,可以使用 `noStore()` 來取代這些使用情境。 + +```jsx +import { unstable_noStore as noStore } from 'next/cache'; + +export default async function ServerComponent() { + noStore(); + const result = await db.query(...); + ... +} +``` + +## 版本歷史 + +| 版本 | 變更內容 | +| ---------- | ----------------------------------------------- | +| `v15.0.0` | `unstable_noStore` 被棄用,改用 `connection`。 | +| `v14.0.0` | `unstable_noStore` 首次引入。 | \ No newline at end of file diff --git a/apps/docs/content/zh-hant/docs/01-app/05-api-reference/04-functions/unstable_rethrow.mdx b/apps/docs/content/zh-hant/docs/01-app/03-api-reference/04-functions/unstable_rethrow.mdx similarity index 100% rename from apps/docs/content/zh-hant/docs/01-app/05-api-reference/04-functions/unstable_rethrow.mdx rename to apps/docs/content/zh-hant/docs/01-app/03-api-reference/04-functions/unstable_rethrow.mdx diff --git a/apps/docs/content/zh-hant/docs/01-app/03-api-reference/04-functions/use-link-status.mdx b/apps/docs/content/zh-hant/docs/01-app/03-api-reference/04-functions/use-link-status.mdx new file mode 100644 index 00000000..96efff12 --- /dev/null +++ b/apps/docs/content/zh-hant/docs/01-app/03-api-reference/04-functions/use-link-status.mdx @@ -0,0 +1,228 @@ +--- +source-updated-at: 2025-08-09T22:43:46.028Z +translation-updated-at: 2025-08-09T22:43:46.028Z +title: useLinkStatus +description: useLinkStatus 鉤子的 API 參考文檔 +related: + title: 下一步 + description: 閱讀 API 參考文檔以了解更多本頁提到的功能 + links: + - app/api-reference/components/link + - app/api-reference/file-conventions/loading +--- + +`useLinkStatus` 鉤子可讓您追蹤 `` 的 **pending** 狀態。您可以使用它在使用者導航到新路由時顯示內嵌的視覺回饋(例如旋轉圖示或文字閃爍)。 + +`useLinkStatus` 在以下情況特別有用: + +- [預取 (Prefetching)](/docs/app/getting-started/linking-and-navigating#prefetching) 被禁用或正在進行中,導致導航被阻擋 +- 目標路由是動態路由 **且** 沒有包含 [`loading.js`](/docs/app/api-reference/file-conventions/loading) 檔案來實現即時導航 + +```tsx filename="app/loading-indicator.tsx" switcher +'use client' + +import { useLinkStatus } from 'next/link' + +export default function LoadingIndicator() { + const { pending } = useLinkStatus() + return pending ? ( +
+ ) : null +} +``` + +```jsx filename="app/loading-indicator.js" switcher +'use client' + +import { useLinkStatus } from 'next/link' + +export default function LoadingIndicator() { + const { pending } = useLinkStatus() + return pending ? ( +
+ ) : null +} +``` + +```tsx filename="app/header.tsx" switcher +import Link from 'next/link' +import LoadingIndicator from './loading-indicator' + +export default function Header() { + return ( +
+ + Dashboard + +
+ ) +} +``` + +```jsx filename="app/header.js" switcher +import Link from 'next/link' +import LoadingIndicator from './loading-indicator' + +export default function Header() { + return ( +
+ + Dashboard + +
+ ) +} +``` + +> **重要須知**: +> +> - `useLinkStatus` 必須在 `Link` 元件的子元件中使用 +> - 當 `Link` 元件設定 `prefetch={false}` 時,此鉤子最為有用 +> - 如果連結路由已被預取,pending 狀態將被跳過 +> - 當快速連續點擊多個連結時,只會顯示最後一個連結的 pending 狀態 +> - 此鉤子在 Pages Router 中不受支援,將始終返回 `{ pending: false }` + +## 參數 + +```tsx +const { pending } = useLinkStatus() +``` + +`useLinkStatus` 不接受任何參數。 + +## 返回值 + +`useLinkStatus` 返回一個包含單一屬性的物件: + +| 屬性 | 類型 | 描述 | +| ------- | -------- | ------------------------------------ | +| pending | boolean | 歷史更新前為 `true`,更新後為 `false` | + +## 範例 + +### 內嵌載入指示器 + +當使用者在預取完成前點擊連結時,添加視覺回饋有助於提示導航正在進行中。 + +```tsx filename="app/components/loading-indicator.tsx" switcher +'use client' + +import { useLinkStatus } from 'next/link' + +export default function LoadingIndicator() { + const { pending } = useLinkStatus() + return pending ? ( +
+ ) : null +} +``` + +```jsx filename="app/components/loading-indicator.js" switcher +'use client' + +import { useLinkStatus } from 'next/link' + +export default function LoadingIndicator() { + const { pending } = useLinkStatus() + return pending ? ( +
+ ) : null +} +``` + +```tsx filename="app/shop/layout.tsx" switcher +import Link from 'next/link' +import LoadingIndicator from './components/loading-indicator' + +const links = [ + { href: '/shop/electronics', label: 'Electronics' }, + { href: '/shop/clothing', label: 'Clothing' }, + { href: '/shop/books', label: 'Books' }, +] + +function Menubar() { + return ( +
+ {links.map((link) => ( + + {link.label} + + ))} +
+ ) +} + +export default function Layout({ children }: { children: React.ReactNode }) { + return ( +
+ + {children} +
+ ) +} +``` + +```jsx filename="app/shop/layout.js" switcher +import Link from 'next/link' +import LoadingIndicator from './components/loading-indicator' + +const links = [ + { href: '/shop/electronics', label: 'Electronics' }, + { href: '/shop/clothing', label: 'Clothing' }, + { href: '/shop/books', label: 'Books' }, +] + +function Menubar() { + return ( +
+ {links.map((link) => ( + + {link.label} + + ))} +
+ ) +} + +export default function Layout({ children }) { + return ( +
+ + {children} +
+ ) +} +``` + +## 優雅處理快速導航 + +如果導航到新路由的速度很快,使用者可能會看到不必要的載入指示器閃爍。一種改善使用者體驗的方法是添加初始動畫延遲(例如 100ms)並以不可見狀態(例如 `opacity: 0`)開始動畫,這樣只有在導航耗時較長時才會顯示載入指示器。 + +```css filename="app/styles/global.css" +.spinner { + /* ... */ + opacity: 0; + animation: + fadeIn 500ms 100ms forwards, + rotate 1s linear infinite; +} + +@keyframes fadeIn { + from { + opacity: 0; + } + to { + opacity: 1; + } +} + +@keyframes rotate { + to { + transform: rotate(360deg); + } +} +``` + +| 版本 | 變更 | +| --------- | ------------------------ | +| `v15.3.0` | 新增 `useLinkStatus` 鉤子 | \ No newline at end of file diff --git a/apps/docs/content/zh-hant/docs/01-app/03-api-reference/04-functions/use-params.mdx b/apps/docs/content/zh-hant/docs/01-app/03-api-reference/04-functions/use-params.mdx new file mode 100644 index 00000000..c746d8ab --- /dev/null +++ b/apps/docs/content/zh-hant/docs/01-app/03-api-reference/04-functions/use-params.mdx @@ -0,0 +1,75 @@ +--- +source-updated-at: 2025-08-09T22:43:46.028Z +translation-updated-at: 2025-08-09T22:43:46.028Z +title: useParams +description: 關於 useParams 鉤子的 API 參考文件。 +--- + +`useParams` 是一個**客戶端元件 (Client Component)** 鉤子,可讓您讀取由當前 URL 填充的路由[動態參數 (dynamic params)](/docs/app/api-reference/file-conventions/dynamic-routes)。 + +```tsx filename="app/example-client-component.tsx" switcher +'use client' + +import { useParams } from 'next/navigation' + +export default function ExampleClientComponent() { + const params = useParams<{ tag: string; item: string }>() + + // Route -> /shop/[tag]/[item] + // URL -> /shop/shoes/nike-air-max-97 + // `params` -> { tag: 'shoes', item: 'nike-air-max-97' } + console.log(params) + + return '...' +} +``` + +```jsx filename="app/example-client-component.js" switcher +'use client' + +import { useParams } from 'next/navigation' + +export default function ExampleClientComponent() { + const params = useParams() + + // Route -> /shop/[tag]/[item] + // URL -> /shop/shoes/nike-air-max-97 + // `params` -> { tag: 'shoes', item: 'nike-air-max-97' } + console.log(params) + + return '...' +} +``` + +## 參數 + +```tsx +const params = useParams() +``` + +`useParams` 不接受任何參數。 + +## 返回值 + +`useParams` 返回一個包含當前路由已填充[動態參數 (dynamic parameters)](/docs/app/api-reference/file-conventions/dynamic-routes) 的物件。 + +- 物件中的每個屬性都是一個活躍的動態區段 (dynamic segment) +- 屬性名稱是區段名稱,屬性值是區段填充的值 +- 屬性值可能是 `string` 或 `string` 陣列,取決於[動態區段的類型](/docs/app/api-reference/file-conventions/dynamic-routes) +- 如果路由不包含動態參數,`useParams` 會返回一個空物件 +- 如果在頁面路由 (Pages Router) 中使用,`useParams` 會在初始渲染時返回 `null`,並在路由器準備就緒後按照上述規則更新屬性 + +例如: + +| 路由 | URL | `useParams()` | +| ------------------------------- | ----------- | ------------------------- | +| `app/shop/page.js` | `/shop` | `{}` | +| `app/shop/[slug]/page.js` | `/shop/1` | `{ slug: '1' }` | +| `app/shop/[tag]/[item]/page.js` | `/shop/1/2` | `{ tag: '1', item: '2' }` | +| `app/shop/[...slug]/page.js` | `/shop/1/2` | `{ slug: ['1', '2'] }` | + +## 版本歷史 + +| 版本 | 變更內容 | +| --------- | ----------------------- | +| `v13.3.0` | 引入 `useParams` 鉤子。 | \ No newline at end of file diff --git a/apps/docs/content/zh-hant/docs/01-app/05-api-reference/04-functions/use-pathname.mdx b/apps/docs/content/zh-hant/docs/01-app/03-api-reference/04-functions/use-pathname.mdx similarity index 100% rename from apps/docs/content/zh-hant/docs/01-app/05-api-reference/04-functions/use-pathname.mdx rename to apps/docs/content/zh-hant/docs/01-app/03-api-reference/04-functions/use-pathname.mdx diff --git a/apps/docs/content/zh-hant/docs/01-app/03-api-reference/04-functions/use-report-web-vitals.mdx b/apps/docs/content/zh-hant/docs/01-app/03-api-reference/04-functions/use-report-web-vitals.mdx new file mode 100644 index 00000000..3fc337e3 --- /dev/null +++ b/apps/docs/content/zh-hant/docs/01-app/03-api-reference/04-functions/use-report-web-vitals.mdx @@ -0,0 +1,246 @@ +--- +source-updated-at: 2025-08-09T22:43:46.028Z +translation-updated-at: 2025-08-09T22:43:46.028Z +title: useReportWebVitals +description: 關於 useReportWebVitals 函式的 API 參考文件。 +--- + +{/* 此文件內容在 App 和 Pages 路由間共享。您可以使用 `內容` 元件來添加特定於 Pages 路由的內容。任何共享內容都不應包裹在元件中。 */} + +`useReportWebVitals` 鉤子允許您報告 [核心 Web 指標 (Core Web Vitals)](https://web.dev/vitals/),並可與您的分析服務結合使用。 + +傳遞給 `useReportWebVitals` 的新函式會使用當前可用的指標進行呼叫。為避免報告重複數據,請確保回調函式引用不變更(如下方程式碼範例所示)。 + + + +```jsx filename="pages/_app.js" +import { useReportWebVitals } from 'next/web-vitals' + +const logWebVitals = (metric) => { + console.log(metric) +} + +function MyApp({ Component, pageProps }) { + useReportWebVitals(logWebVitals) + + return +} +``` + + + + + +```jsx filename="app/_components/web-vitals.js" +'use client' + +import { useReportWebVitals } from 'next/web-vitals' + +const logWebVitals = (metric) => { + console.log(metric) +} + +export function WebVitals() { + useReportWebVitals(logWebVitals) + + return null +} +``` + +```jsx filename="app/layout.js" +import { WebVitals } from './_components/web-vitals' + +export default function Layout({ children }) { + return ( + + + + {children} + + + ) +} +``` + +> 由於 `useReportWebVitals` 鉤子需要 `'use client'` 指令,最有效的方法是建立一個由根佈局導入的獨立元件。這樣可以將客戶端邊界僅限於 `WebVitals` 元件。 + + + +## useReportWebVitals + +作為鉤子參數傳遞的 `metric` 物件包含以下屬性: + +- `id`:當前頁面加載上下文中指標的唯一識別碼 +- `name`:效能指標的名稱。可能的值包括特定於 Web 應用程式的 [Web 指標](#web-vitals) 名稱(TTFB、FCP、LCP、FID、CLS) +- `delta`:指標當前值與先前值的差異。該值通常以毫秒為單位,表示指標值隨時間的變化 +- `entries`:與指標相關聯的 [效能條目 (Performance Entries)](https://developer.mozilla.org/docs/Web/API/PerformanceEntry) 陣列。這些條目提供有關指標相關效能事件的詳細資訊 +- `navigationType`:指示觸發指標收集的 [導航類型](https://developer.mozilla.org/docs/Web/API/PerformanceNavigationTiming/type)。可能的值包括 `"navigate"`、`"reload"`、`"back_forward"` 和 `"prerender"` +- `rating`:指標值的定性評級,提供效能評估。可能的值為 `"good"`、`"needs-improvement"` 和 `"poor"`。評級通常是通過將指標值與指示可接受或次優效能的預定義閾值進行比較來確定的 +- `value`:效能條目的實際值或持續時間,通常以毫秒為單位。該值提供指標追蹤的效能方面的定量測量。值的來源取決於所測量的特定指標,可以來自各種 [效能 API (Performance API)](https://developer.mozilla.org/docs/Web/API/Performance_API) + +## Web 指標 + +[Web 指標 (Web Vitals)](https://web.dev/vitals/) 是一組有用的指標,旨在捕捉網頁的用戶體驗。包含以下所有 Web 指標: + +- [首次位元組時間 (Time to First Byte)](https://developer.mozilla.org/docs/Glossary/Time_to_first_byte) (TTFB) +- [首次內容繪製 (First Contentful Paint)](https://developer.mozilla.org/docs/Glossary/First_contentful_paint) (FCP) +- [最大內容繪製 (Largest Contentful Paint)](https://web.dev/lcp/) (LCP) +- [首次輸入延遲 (First Input Delay)](https://web.dev/fid/) (FID) +- [累積版面配置位移 (Cumulative Layout Shift)](https://web.dev/cls/) (CLS) +- [互動到下一個繪製 (Interaction to Next Paint)](https://web.dev/inp/) (INP) + +您可以使用 `name` 屬性處理這些指標的所有結果。 + + + +```jsx filename="pages/_app.js" +import { useReportWebVitals } from 'next/web-vitals' + +const handleWebVitals = (metric) => { + switch (metric.name) { + case 'FCP': { + // 處理 FCP 結果 + } + case 'LCP': { + // 處理 LCP 結果 + } + // ... + } +} + +function MyApp({ Component, pageProps }) { + useReportWebVitals(handleWebVitals) + + return +} +``` + + + + + +```tsx filename="app/components/web-vitals.tsx" switcher +'use client' + +import { useReportWebVitals } from 'next/web-vitals' + +type ReportWebVitalsCallback = Parameters[0] + +const handleWebVitals: ReportWebVitalsCallback = (metric) => { + switch (metric.name) { + case 'FCP': { + // 處理 FCP 結果 + } + case 'LCP': { + // 處理 LCP 結果 + } + // ... + } +} + +export function WebVitals() { + useReportWebVitals(handleWebVitals) +} +``` + +```jsx filename="app/components/web-vitals.js" switcher +'use client' + +import { useReportWebVitals } from 'next/web-vitals' + +const handleWebVitals = (metric) => { + switch (metric.name) { + case 'FCP': { + // 處理 FCP 結果 + } + case 'LCP': { + // 處理 LCP 結果 + } + // ... + } +} + +export function WebVitals() { + useReportWebVitals(handleWebVitals) +} +``` + + + + + +## 自訂指標 + +除了上述核心指標外,還有一些額外的自訂指標用於測量頁面水合 (hydrate) 和渲染所需的時間: + +- `Next.js-hydration`:頁面開始和完成水合所需的時間(以毫秒為單位) +- `Next.js-route-change-to-render`:路由變更後頁面開始渲染所需的時間(以毫秒為單位) +- `Next.js-render`:路由變更後頁面完成渲染所需的時間(以毫秒為單位) + +您可以單獨處理這些指標的所有結果: + +```jsx filename="pages/_app.js" +import { useReportWebVitals } from 'next/web-vitals' + +function handleCustomMetrics(metrics) { + switch (metric.name) { + case 'Next.js-hydration': + // 處理水合結果 + break + case 'Next.js-route-change-to-render': + // 處理路由變更到渲染的結果 + break + case 'Next.js-render': + // 處理渲染結果 + break + default: + break + } +} + +function MyApp({ Component, pageProps }) { + useReportWebVitals(handleCustomMetrics) + + return +} +``` + +這些指標適用於所有支援 [用戶計時 API (User Timing API)](https://caniuse.com/#feat=user-timing) 的瀏覽器。 + + + +## 將結果發送到外部系統 + +您可以將結果發送到任何端點以測量和追蹤您網站上的真實用戶效能。例如: + +```js +function postWebVitals(metrics) { + const body = JSON.stringify(metric) + const url = 'https://example.com/analytics' + + // 如果可用,使用 `navigator.sendBeacon()`,否則回退到 `fetch()` + if (navigator.sendBeacon) { + navigator.sendBeacon(url, body) + } else { + fetch(url, { body, method: 'POST', keepalive: true }) + } +} + +useReportWebVitals(postWebVitals) +``` + +> **須知**:如果您使用 [Google Analytics](https://analytics.google.com/analytics/web/),使用 `id` 值可以讓您手動構建指標分佈(以計算百分位數等) + +> ```js +> useReportWebVitals(metric => { +> // 如果您像此範例一樣初始化了 Google Analytics,請使用 `window.gtag`: +> // https://github.com/vercel/next.js/blob/canary/examples/with-google-analytics +> window.gtag('event', metric.name, { +> value: Math.round(metric.name === 'CLS' ? metric.value * 1000 : metric.value), // 值必須為整數 +> event_label: metric.id, // 當前頁面加載的唯一 id +> non_interaction: true, // 避免影響跳出率 +> }); +> } +> ``` +> +> 閱讀更多關於 [將結果發送到 Google Analytics](https://github.com/GoogleChrome/web-vitals#send-the-results-to-google-analytics) 的資訊。 \ No newline at end of file diff --git a/apps/docs/content/zh-hant/docs/01-app/05-api-reference/04-functions/use-router.mdx b/apps/docs/content/zh-hant/docs/01-app/03-api-reference/04-functions/use-router.mdx similarity index 100% rename from apps/docs/content/zh-hant/docs/01-app/05-api-reference/04-functions/use-router.mdx rename to apps/docs/content/zh-hant/docs/01-app/03-api-reference/04-functions/use-router.mdx diff --git a/apps/docs/content/zh-hant/docs/01-app/05-api-reference/04-functions/use-search-params.mdx b/apps/docs/content/zh-hant/docs/01-app/03-api-reference/04-functions/use-search-params.mdx similarity index 100% rename from apps/docs/content/zh-hant/docs/01-app/05-api-reference/04-functions/use-search-params.mdx rename to apps/docs/content/zh-hant/docs/01-app/03-api-reference/04-functions/use-search-params.mdx diff --git a/apps/docs/content/zh-hant/docs/01-app/03-api-reference/04-functions/use-selected-layout-segment.mdx b/apps/docs/content/zh-hant/docs/01-app/03-api-reference/04-functions/use-selected-layout-segment.mdx new file mode 100644 index 00000000..88f5f1e6 --- /dev/null +++ b/apps/docs/content/zh-hant/docs/01-app/03-api-reference/04-functions/use-selected-layout-segment.mdx @@ -0,0 +1,174 @@ +--- +source-updated-at: 2025-08-09T22:43:46.028Z +translation-updated-at: 2025-08-09T22:43:46.028Z +title: useSelectedLayoutSegment +description: useSelectedLayoutSegment 鉤子的 API 參考文件 +--- + +`useSelectedLayoutSegment` 是一個 **客戶端元件 (Client Component)** 鉤子,可讓您讀取從中呼叫的 Layout **下方一層** 的當前路由區段。 + +這對於導航 UI 非常有用,例如父佈局中的標籤頁,可以根據當前活動的子區段改變樣式。 + +```tsx filename="app/example-client-component.tsx" switcher +'use client' + +import { useSelectedLayoutSegment } from 'next/navigation' + +export default function ExampleClientComponent() { + const segment = useSelectedLayoutSegment() + + return

當前活動區段: {segment}

+} +``` + +```jsx filename="app/example-client-component.js" switcher +'use client' + +import { useSelectedLayoutSegment } from 'next/navigation' + +export default function ExampleClientComponent() { + const segment = useSelectedLayoutSegment() + + return

當前活動區段: {segment}

+} +``` + +> **須知事項**: +> +> - 由於 `useSelectedLayoutSegment` 是一個 [客戶端元件 (Client Component)](/docs/app/getting-started/server-and-client-components) 鉤子,而佈局 (Layouts) 預設是 [伺服器元件 (Server Components)](/docs/app/getting-started/server-and-client-components),因此 `useSelectedLayoutSegment` 通常透過導入到佈局中的客戶端元件來呼叫。 +> - `useSelectedLayoutSegment` 只會返回下一層的區段。若要返回所有活動區段,請參閱 [`useSelectedLayoutSegments`](/docs/app/api-reference/functions/use-selected-layout-segments) + +## 參數 + +```tsx +const segment = useSelectedLayoutSegment(parallelRoutesKey?: string) +``` + +`useSelectedLayoutSegment` 可選擇性接受一個 [`parallelRoutesKey`](/docs/app/api-reference/file-conventions/parallel-routes#with-useselectedlayoutsegments),允許您讀取該插槽內的當前路由區段。 + +## 返回值 + +`useSelectedLayoutSegment` 返回當前活動區段的字串,若不存在則返回 `null`。 + +例如,根據以下佈局和訪問的 URL,返回的區段將會是: + +| 佈局 | 訪問的 URL | 返回的區段 | +| ------------------------- | ------------------------------ | ---------------- | +| `app/layout.js` | `/` | `null` | +| `app/layout.js` | `/dashboard` | `'dashboard'` | +| `app/dashboard/layout.js` | `/dashboard` | `null` | +| `app/dashboard/layout.js` | `/dashboard/settings` | `'settings'` | +| `app/dashboard/layout.js` | `/dashboard/analytics` | `'analytics'` | +| `app/dashboard/layout.js` | `/dashboard/analytics/monthly` | `'analytics'` | + +## 範例 + +### 建立當前活動連結元件 + +您可以使用 `useSelectedLayoutSegment` 來建立一個會根據當前活動區段改變樣式的連結元件。例如,部落格側邊欄中的精選文章列表: + +```tsx filename="app/blog/blog-nav-link.tsx" switcher +'use client' + +import Link from 'next/link' +import { useSelectedLayoutSegment } from 'next/navigation' + +// 這個 *客戶端* 元件將被導入到部落格佈局中 +export default function BlogNavLink({ + slug, + children, +}: { + slug: string + children: React.ReactNode +}) { + // 導航至 `/blog/hello-world` 將返回 'hello-world' + // 作為選中的佈局區段 + const segment = useSelectedLayoutSegment() + const isActive = slug === segment + + return ( + + {children} + + ) +} +``` + +```jsx filename="app/blog/blog-nav-link.js" switcher +'use client' + +import Link from 'next/link' +import { useSelectedLayoutSegment } from 'next/navigation' + +// 這個 *客戶端* 元件將被導入到部落格佈局中 +export default function BlogNavLink({ slug, children }) { + // 導航至 `/blog/hello-world` 將返回 'hello-world' + // 作為選中的佈局區段 + const segment = useSelectedLayoutSegment() + const isActive = slug === segment + + return ( + + {children} + + ) +} +``` + +```tsx filename="app/blog/layout.tsx" switcher +// 將客戶端元件導入到父佈局 (伺服器元件) 中 +import { BlogNavLink } from './blog-nav-link' +import getFeaturedPosts from './get-featured-posts' + +export default async function Layout({ + children, +}: { + children: React.ReactNode +}) { + const featuredPosts = await getFeaturedPosts() + return ( +
+ {featuredPosts.map((post) => ( +
+ {post.title} +
+ ))} +
{children}
+
+ ) +} +``` + +```jsx filename="app/blog/layout.js" switcher +// 將客戶端元件導入到父佈局 (伺服器元件) 中 +import { BlogNavLink } from './blog-nav-link' +import getFeaturedPosts from './get-featured-posts' + +export default async function Layout({ children }) { + const featuredPosts = await getFeaturedPosts() + return ( +
+ {featuredPosts.map((post) => ( +
+ {post.title} +
+ ))} +
{children}
+
+ ) +} +``` + +## 版本歷史 + +| 版本 | 變更內容 | +| --------- | -------------------------------------- | +| `v13.0.0` | 引入 `useSelectedLayoutSegment`。 | \ No newline at end of file diff --git a/apps/docs/content/zh-hant/docs/01-app/03-api-reference/04-functions/use-selected-layout-segments.mdx b/apps/docs/content/zh-hant/docs/01-app/03-api-reference/04-functions/use-selected-layout-segments.mdx new file mode 100644 index 00000000..7972a612 --- /dev/null +++ b/apps/docs/content/zh-hant/docs/01-app/03-api-reference/04-functions/use-selected-layout-segments.mdx @@ -0,0 +1,79 @@ +--- +source-updated-at: 2025-08-09T22:43:46.028Z +translation-updated-at: 2025-08-09T22:43:46.028Z +title: useSelectedLayoutSegments +description: 關於 useSelectedLayoutSegments 鉤子的 API 參考文件。 +--- + +`useSelectedLayoutSegments` 是一個**客戶端元件 (Client Component)** 鉤子,可讓您讀取從中呼叫此鉤子的佈局 (Layout) **下方**的當前路由區段 (segments)。 + +這對於需要在父佈局中建立了解子區段狀態的 UI(例如麵包屑導航)非常有用。 + +```tsx filename="app/example-client-component.tsx" switcher +'use client' + +import { useSelectedLayoutSegments } from 'next/navigation' + +export default function ExampleClientComponent() { + const segments = useSelectedLayoutSegments() + + return ( +
    + {segments.map((segment, index) => ( +
  • {segment}
  • + ))} +
+ ) +} +``` + +```jsx filename="app/example-client-component.js" switcher +'use client' + +import { useSelectedLayoutSegments } from 'next/navigation' + +export default function ExampleClientComponent() { + const segments = useSelectedLayoutSegments() + + return ( +
    + {segments.map((segment, index) => ( +
  • {segment}
  • + ))} +
+ ) +} +``` + +> **須知事項**: +> +> - 由於 `useSelectedLayoutSegments` 是一個[客戶端元件 (Client Component)](/docs/app/getting-started/server-and-client-components) 鉤子,而佈局預設是[伺服器元件 (Server Component)](/docs/app/getting-started/server-and-client-components),因此通常會透過導入佈局的客戶端元件來呼叫 `useSelectedLayoutSegments`。 +> - 返回的區段包含[路由群組 (Route Groups)](/docs/app/api-reference/file-conventions/route-groups),您可能不希望這些內容出現在 UI 中。可以使用 [`filter`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter) 陣列方法來移除以括號開頭的項目。 + +## 參數 + +```tsx +const segments = useSelectedLayoutSegments(parallelRoutesKey?: string) +``` + +`useSelectedLayoutSegments` _可選地_ 接受一個 [`parallelRoutesKey`](/docs/app/api-reference/file-conventions/parallel-routes#with-useselectedlayoutsegments) 參數,允許您讀取該插槽內的有效路由區段。 + +## 返回值 + +`useSelectedLayoutSegments` 返回一個字串陣列,包含從呼叫此鉤子的佈局往下一個層級的有效區段。如果不存在則返回空陣列。 + +例如,根據以下佈局和訪問的 URL,返回的區段會是: + +| 佈局 | 訪問的 URL | 返回的區段 | +| ------------------------- | --------------------- | --------------------------- | +| `app/layout.js` | `/` | `[]` | +| `app/layout.js` | `/dashboard` | `['dashboard']` | +| `app/layout.js` | `/dashboard/settings` | `['dashboard', 'settings']` | +| `app/dashboard/layout.js` | `/dashboard` | `[]` | +| `app/dashboard/layout.js` | `/dashboard/settings` | `['settings']` | + +## 版本歷史 + +| 版本 | 變更內容 | +| --------- | --------------------------------------- | +| `v13.0.0` | 新增 `useSelectedLayoutSegments` 功能。 | \ No newline at end of file diff --git a/apps/docs/content/zh-hant/docs/01-app/03-api-reference/04-functions/userAgent.mdx b/apps/docs/content/zh-hant/docs/01-app/03-api-reference/04-functions/userAgent.mdx new file mode 100644 index 00000000..65bb2d57 --- /dev/null +++ b/apps/docs/content/zh-hant/docs/01-app/03-api-reference/04-functions/userAgent.mdx @@ -0,0 +1,81 @@ +--- +source-updated-at: 2025-08-09T22:43:46.028Z +translation-updated-at: 2025-08-09T22:43:46.028Z +title: userAgent +description: 此 userAgent 輔助工具擴展了 Web Request API,提供額外屬性和方法來與請求中的使用者代理物件互動。 +--- + +{/* 此文件內容在應用程式路由和頁面路由之間共享。您可以使用 `內容` 元件來新增專屬於頁面路由的內容。任何共享內容不應被包裹在元件中。 */} + +`userAgent` 輔助工具擴展了 [Web Request API](https://developer.mozilla.org/docs/Web/API/Request),提供額外屬性和方法來與請求中的使用者代理物件互動。 + +```ts filename="middleware.ts" switcher +import { NextRequest, NextResponse, userAgent } from 'next/server' + +export function middleware(request: NextRequest) { + const url = request.nextUrl + const { device } = userAgent(request) + + // device.type 可能為: 'mobile', 'tablet', 'console', 'smarttv', + // 'wearable', 'embedded', 或 undefined (桌面瀏覽器) + const viewport = device.type || 'desktop' + + url.searchParams.set('viewport', viewport) + return NextResponse.rewrite(url) +} +``` + +```js filename="middleware.js" switcher +import { NextResponse, userAgent } from 'next/server' + +export function middleware(request) { + const url = request.nextUrl + const { device } = userAgent(request) + + // device.type 可能為: 'mobile', 'tablet', 'console', 'smarttv', + // 'wearable', 'embedded', 或 undefined (桌面瀏覽器) + const viewport = device.type || 'desktop' + + url.searchParams.set('viewport', viewport) + return NextResponse.rewrite(url) +} +``` + +## `isBot` + +布林值,表示請求是否來自已知的爬蟲程式。 + +## `browser` + +包含請求中使用瀏覽器資訊的物件。 + +- `name`: 字串,表示瀏覽器名稱,若無法識別則為 `undefined` +- `version`: 字串,表示瀏覽器版本,若無法識別則為 `undefined` + +## `device` + +包含請求中使用裝置資訊的物件。 + +- `model`: 字串,表示裝置型號,若無法識別則為 `undefined` +- `type`: 字串,表示裝置類型,可能值為 `console`、`mobile`、`tablet`、`smarttv`、`wearable`、`embedded` 或 `undefined` +- `vendor`: 字串,表示裝置製造商,若無法識別則為 `undefined` + +## `engine` + +包含瀏覽器引擎資訊的物件。 + +- `name`: 字串,表示引擎名稱。可能值包括: `Amaya`、`Blink`、`EdgeHTML`、`Flow`、`Gecko`、`Goanna`、`iCab`、`KHTML`、`Links`、`Lynx`、`NetFront`、`NetSurf`、`Presto`、`Tasman`、`Trident`、`w3m`、`WebKit` 或 `undefined` +- `version`: 字串,表示引擎版本,若無法識別則為 `undefined` + +## `os` + +包含作業系統資訊的物件。 + +- `name`: 字串,表示作業系統名稱,若無法識別則為 `undefined` +- `version`: 字串,表示作業系統版本,若無法識別則為 `undefined` + +## `cpu` + +包含 CPU 架構資訊的物件。 + +- `architecture`: 字串,表示 CPU 架構。可能值包括: `68k`、`amd64`、`arm`、`arm64`、`armhf`、`avr`、`ia32`、`ia64`、`irix`、`irix64`、`mips`、`mips64`、`pa-risc`、`ppc`、`sparc`、`sparc64` 或 `undefined` \ No newline at end of file diff --git a/apps/docs/content/zh-hant/docs/01-app/03-api-reference/05-config/01-next-config-js/allowedDevOrigins.mdx b/apps/docs/content/zh-hant/docs/01-app/03-api-reference/05-config/01-next-config-js/allowedDevOrigins.mdx new file mode 100644 index 00000000..0d9ee764 --- /dev/null +++ b/apps/docs/content/zh-hant/docs/01-app/03-api-reference/05-config/01-next-config-js/allowedDevOrigins.mdx @@ -0,0 +1,20 @@ +--- +source-updated-at: 2025-08-09T22:43:46.028Z +translation-updated-at: 2025-08-09T22:43:46.028Z +title: allowedDevOrigins +description: 使用 `allowedDevOrigins` 來設定可向開發伺服器發送請求的額外來源。 +--- + +{/* 此文件內容同時適用於 app 和 pages 路由。您可以使用 `內容` 元件來新增專屬於 Pages Router 的內容。任何共享內容不應被包裹在元件中。 */} + +Next.js 在開發期間不會自動阻擋跨來源請求,但在未來的重大版本中預設將會阻擋,以防止在開發模式下未經授權存取內部資源/端點。 + +若要設定 Next.js 應用程式允許來自伺服器初始化主機名稱 (預設為 `localhost`) 以外的來源請求,您可以使用 `allowedDevOrigins` 設定選項。 + +`allowedDevOrigins` 允許您設定在開發模式下可使用的額外來源。例如,若要使用 `local-origin.dev` 而非僅限 `localhost`,請開啟 `next.config.js` 並新增 `allowedDevOrigins` 設定: + +```js filename="next.config.js" +module.exports = { + allowedDevOrigins: ['local-origin.dev', '*.local-origin.dev'], +} +``` \ No newline at end of file diff --git a/apps/docs/content/zh-hant/docs/01-app/05-api-reference/05-config/01-next-config-js/appDir.mdx b/apps/docs/content/zh-hant/docs/01-app/03-api-reference/05-config/01-next-config-js/appDir.mdx similarity index 100% rename from apps/docs/content/zh-hant/docs/01-app/05-api-reference/05-config/01-next-config-js/appDir.mdx rename to apps/docs/content/zh-hant/docs/01-app/03-api-reference/05-config/01-next-config-js/appDir.mdx diff --git a/apps/docs/content/zh-hant/docs/01-app/03-api-reference/05-config/01-next-config-js/assetPrefix.mdx b/apps/docs/content/zh-hant/docs/01-app/03-api-reference/05-config/01-next-config-js/assetPrefix.mdx new file mode 100644 index 00000000..54cc349c --- /dev/null +++ b/apps/docs/content/zh-hant/docs/01-app/03-api-reference/05-config/01-next-config-js/assetPrefix.mdx @@ -0,0 +1,77 @@ +--- +source-updated-at: 2025-08-09T22:43:46.028Z +translation-updated-at: 2025-08-09T22:43:46.028Z +title: assetPrefix +description: 了解如何使用 assetPrefix 配置選項來設定您的 CDN。 +--- + +{/* 此文件內容在應用程式路由器和頁面路由器之間共享。您可以使用 `內容` 元件來新增專屬於頁面路由器的內容。任何共享內容不應包裹在元件中。 */} + + + +> **注意**: [部署到 Vercel](/docs/app/getting-started/deploying) 會自動為您的 Next.js 專案設定全域 CDN。 +> 您不需要手動設定 Asset Prefix。 + + + + + +> **注意**: [部署到 Vercel](/docs/pages/getting-started/deploying) 會自動為您的 Next.js 專案設定全域 CDN。 +> 您不需要手動設定 Asset Prefix。 + + + +> **須知**: Next.js 9.5+ 新增了對可自訂 [Base Path](/docs/app/api-reference/config/next-config-js/basePath) 的支援,更適合將應用程式託管在子路徑下,例如 `/docs`。 +> 我們不建議在此使用情境下使用自訂的 Asset Prefix。 + +## 設定 CDN + +要設定 [CDN](https://en.wikipedia.org/wiki/Content_delivery_network),您可以設定 asset prefix 並配置您的 CDN 來源,使其解析到託管 Next.js 的網域。 + +開啟 `next.config.mjs` 並根據 [phase](/docs/app/api-reference/config/next-config-js#async-configuration) 新增 `assetPrefix` 配置: + +```js filename="next.config.mjs" +// @ts-check +import { PHASE_DEVELOPMENT_SERVER } from 'next/constants' + +export default (phase) => { + const isDev = phase === PHASE_DEVELOPMENT_SERVER + /** + * @type {import('next').NextConfig} + */ + const nextConfig = { + assetPrefix: isDev ? undefined : 'https://cdn.mydomain.com', + } + return nextConfig +} +``` + +Next.js 會自動對從 `/_next/` 路徑 (`.next/static/` 資料夾) 載入的 JavaScript 和 CSS 檔案使用您的 asset prefix。例如,使用上述配置後,對 JS chunk 的請求: + +``` +/_next/static/chunks/4b9b41aaa062cbbfeff4add70f256968c51ece5d.4d708494b3aed70c04f0.js +``` + +將會變為: + +``` +https://cdn.mydomain.com/_next/static/chunks/4b9b41aaa062cbbfeff4add70f256968c51ece5d.4d708494b3aed70c04f0.js +``` + +將檔案上傳到指定 CDN 的確切配置取決於您選擇的 CDN。您只需要在 CDN 上託管的資料夾是 `.next/static/` 的內容,應如上方的 URL 請求所示,以 `_next/static/` 形式上傳。**請勿上傳 `.next/` 資料夾的其餘部分**,因為您不應將伺服器代碼和其他配置公開。 + +雖然 `assetPrefix` 涵蓋了對 `_next/static` 的請求,但不會影響以下路徑: + + + +- [public](/docs/app/api-reference/file-conventions/public-folder) 資料夾中的檔案;如果您想透過 CDN 提供這些資源,必須自行加入前綴 + + + + + +- [public](/docs/pages/api-reference/file-conventions/public-folder) 資料夾中的檔案;如果您想透過 CDN 提供這些資源,必須自行加入前綴 +- 針對 `getServerSideProps` 頁面的 `/_next/data/` 請求。這些請求始終會針對主網域發出,因為它們不是靜態的。 +- 針對 `getStaticProps` 頁面的 `/_next/data/` 請求。這些請求始終會針對主網域發出,以支援 [增量靜態生成 (Incremental Static Generation)](/docs/pages/guides/incremental-static-regeneration),即使您沒有使用此功能(為了保持一致性)。 + + \ No newline at end of file diff --git a/apps/docs/content/zh-hant/docs/01-app/03-api-reference/05-config/01-next-config-js/authInterrupts.mdx b/apps/docs/content/zh-hant/docs/01-app/03-api-reference/05-config/01-next-config-js/authInterrupts.mdx new file mode 100644 index 00000000..b41dc82c --- /dev/null +++ b/apps/docs/content/zh-hant/docs/01-app/03-api-reference/05-config/01-next-config-js/authInterrupts.mdx @@ -0,0 +1,35 @@ +--- +source-updated-at: 2025-08-09T22:43:46.028Z +translation-updated-at: 2025-08-09T22:43:46.028Z +title: authInterrupts +description: 了解如何啟用實驗性的 `authInterrupts` 配置選項來使用 `forbidden` 和 `unauthorized`。 +version: canary +related: + links: + - app/api-reference/functions/forbidden + - app/api-reference/functions/unauthorized + - app/api-reference/file-conventions/forbidden + - app/api-reference/file-conventions/unauthorized +--- + +`authInterrupts` 配置選項允許您在應用程式中使用 [`forbidden`](/docs/app/api-reference/functions/forbidden) 和 [`unauthorized`](/docs/app/api-reference/functions/unauthorized) API。雖然這些功能目前處於實驗階段,您必須在 `next.config.js` 檔案中啟用 `authInterrupts` 選項才能使用它們: + +```ts filename="next.config.ts" switcher +import type { NextConfig } from 'next' + +const nextConfig: NextConfig = { + experimental: { + authInterrupts: true, + }, +} + +export default nextConfig +``` + +```js filename="next.config.js" switcher +module.exports = { + experimental: { + authInterrupts: true, + }, +} +``` \ No newline at end of file diff --git a/apps/docs/content/zh-hant/docs/01-app/03-api-reference/05-config/01-next-config-js/basePath.mdx b/apps/docs/content/zh-hant/docs/01-app/03-api-reference/05-config/01-next-config-js/basePath.mdx new file mode 100644 index 00000000..a1e23a9d --- /dev/null +++ b/apps/docs/content/zh-hant/docs/01-app/03-api-reference/05-config/01-next-config-js/basePath.mdx @@ -0,0 +1,81 @@ +--- +source-updated-at: 2025-08-09T22:43:46.028Z +translation-updated-at: 2025-08-09T22:43:46.028Z +title: basePath +description: 使用 `basePath` 將 Next.js 應用程式部署在網域的子路徑下。 +--- + +{/* 此文件內容在應用程式路由和頁面路由之間共享。您可以使用 `內容` 元件來新增專屬於頁面路由的內容。任何共享內容不應被包裹在元件中。 */} + +要將 Next.js 應用程式部署在網域的子路徑下,您可以使用 `basePath` 配置選項。 + +`basePath` 允許您為應用程式設定路徑前綴。例如,要使用 `/docs` 而非預設的 `''`(空字串),請開啟 `next.config.js` 並新增 `basePath` 配置: + +```js filename="next.config.js" +module.exports = { + basePath: '/docs', +} +``` + +> **須知**:此值必須在構建時設定,且無法在不重新構建的情況下變更,因為該值會被內嵌到客戶端套件中。 + +### 連結 + +當使用 `next/link` 和 `next/router` 連結到其他頁面時,`basePath` 會自動被應用。 + +例如,當 `basePath` 設定為 `/docs` 時,使用 `/about` 會自動變成 `/docs/about`。 + +```js +export default function HomePage() { + return ( + <> + About Page + + ) +} +``` + +輸出的 html: + +```html +About Page +``` + +這確保您在變更 `basePath` 值時,無需更改應用程式中的所有連結。 + +### 圖片 + + + +當使用 [`next/image`](/docs/app/api-reference/components/image) 元件時,您需要在 `src` 前面加上 `basePath`。 + + + + + +當使用 [`next/image`](/docs/pages/api-reference/components/image) 元件時,您需要在 `src` 前面加上 `basePath`。 + + + +例如,當 `basePath` 設定為 `/docs` 時,使用 `/docs/me.png` 將正確提供您的圖片。 + +```jsx +import Image from 'next/image' + +function Home() { + return ( + <> +

我的首頁

+ 作者的照片 +

歡迎來到我的首頁!

+ + ) +} + +export default Home +``` \ No newline at end of file diff --git a/apps/docs/content/zh-hant/docs/01-app/05-api-reference/05-config/01-next-config-js/dynamicIO.mdx b/apps/docs/content/zh-hant/docs/01-app/03-api-reference/05-config/01-next-config-js/cacheComponents.mdx similarity index 100% rename from apps/docs/content/zh-hant/docs/01-app/05-api-reference/05-config/01-next-config-js/dynamicIO.mdx rename to apps/docs/content/zh-hant/docs/01-app/03-api-reference/05-config/01-next-config-js/cacheComponents.mdx diff --git a/apps/docs/content/zh-hant/docs/01-app/05-api-reference/05-config/01-next-config-js/cacheLife.mdx b/apps/docs/content/zh-hant/docs/01-app/03-api-reference/05-config/01-next-config-js/cacheLife.mdx similarity index 100% rename from apps/docs/content/zh-hant/docs/01-app/05-api-reference/05-config/01-next-config-js/cacheLife.mdx rename to apps/docs/content/zh-hant/docs/01-app/03-api-reference/05-config/01-next-config-js/cacheLife.mdx diff --git a/apps/docs/content/zh-hant/docs/01-app/03-api-reference/05-config/01-next-config-js/compress.mdx b/apps/docs/content/zh-hant/docs/01-app/03-api-reference/05-config/01-next-config-js/compress.mdx new file mode 100644 index 00000000..fc6533c4 --- /dev/null +++ b/apps/docs/content/zh-hant/docs/01-app/03-api-reference/05-config/01-next-config-js/compress.mdx @@ -0,0 +1,24 @@ +--- +source-updated-at: 2025-08-09T22:43:46.028Z +translation-updated-at: 2025-08-09T22:43:46.028Z +title: compress +description: Next.js 提供 gzip 壓縮功能來壓縮渲染內容和靜態檔案,此功能僅適用於伺服器目標。了解更多相關資訊。 +--- + +{/* 此文件內容在應用程式路由和頁面路由之間共享。您可以使用 `內容` 元件來添加專屬於頁面路由的內容。任何共享內容不應包裹在元件中。 */} + +預設情況下,當使用 `next start` 或自訂伺服器時,Next.js 會使用 `gzip` 來壓縮渲染內容和靜態檔案。這是針對未配置壓縮功能的應用程式所做的優化。如果您的應用程式已透過自訂伺服器配置了壓縮功能,Next.js 將不會再次添加壓縮。 + +您可以透過查看回應中的 [`Accept-Encoding`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept-Encoding) (瀏覽器接受的選項) 和 [`Content-Encoding`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Encoding) (當前使用的) 標頭,來檢查壓縮是否啟用以及使用了哪種演算法。 + +## 停用壓縮功能 + +要停用**壓縮**功能,請將 `compress` 配置選項設為 `false`: + +```js filename="next.config.js" +module.exports = { + compress: false, +} +``` + +我們**不建議停用壓縮**功能,除非您已在伺服器上配置了壓縮,因為壓縮能減少頻寬使用並提升應用程式效能。例如,如果您正在使用 [nginx](https://nginx.org/) 並想切換到 `brotli` 壓縮,請將 `compress` 選項設為 `false` 以讓 nginx 處理壓縮。 \ No newline at end of file diff --git a/apps/docs/content/zh-hant/docs/01-app/03-api-reference/05-config/01-next-config-js/crossOrigin.mdx b/apps/docs/content/zh-hant/docs/01-app/03-api-reference/05-config/01-next-config-js/crossOrigin.mdx new file mode 100644 index 00000000..a4f6392c --- /dev/null +++ b/apps/docs/content/zh-hant/docs/01-app/03-api-reference/05-config/01-next-config-js/crossOrigin.mdx @@ -0,0 +1,21 @@ +--- +source-updated-at: 2025-08-09T22:43:46.028Z +translation-updated-at: 2025-08-09T22:43:46.028Z +title: crossOrigin +description: 使用 `crossOrigin` 選項可在 `next/script` 生成的 `script` 標籤上添加跨來源標籤。 +--- + +{/* 此文件內容在應用程式路由器和頁面路由器之間共享。您可以使用 `內容` 元件來添加專屬於頁面路由器的內容。任何共享內容不應包裹在元件中。 */} + +使用 `crossOrigin` 選項可在 [`next/script`](/docs/app/guides/scripts) 元件 [`next/script`](/docs/pages/guides/scripts) 和 [`next/head`](/docs/pages/api-reference/components/head) 元件 生成的所有 `