Payload CMS לוקליזציה: מהגדרות לאינטגרציה עם Next.js
אנו משלבים לוקליזציה ב-Payload CMS לפרויקטים רב-לשוניים על Next.js. נקודות כאב אופייניות: שכפול תוכן בין אוספים שונים, שאילתות N+1 לתרגומי fallback, ו-TTFB איטי עקב סכמה לא אופטימלית. Payload CMS פותר זאת ברמת השדה, אך ללא הגדרות נכונות, אתם עלולים להיתקל בעמודים ריקים או במיגרציות מיותרות.
בעיות שאנו פותרים
שפת fallback ושדות ריקים. אם תרגום חסר, המשתמש רואה בלוק ריק. הגדרת fallback: true בקונפיגורציה פותרת זאת: כאשר מתבקשת שפה שאינה קיימת, הערך מ-defaultLocale מוחלף. אך שימו לב ש-fallback עובד רק עבור שדות המסומנים כ-localized. שדות שאינם מקומיים נשארים משותפים.
כתובות SEO לכל שפה. לעיתים קרובות נדרש לייצר URLs ייחודיים עבור לוקאליים שונים כדי למנוע כפילויות ב-Google. Payload מאפשר לוקליזציה של שדה slug, ו-Next.js App Router יוצר נתיבים כמו /en/posts/hello-world ו-/ru/posts/privet-mir. זה פותר בעיות hreflang ו-CLS בעת מעבר בין שפות.
אופטימיזציית שאילתות. שאילתת locale: 'all' מחזירה את כל התרגומים במסמך אחד—פתרון שטחי. לביצועים טובים יותר, השתמשו בשאילתות נפרדות לכל לוקאל עם caching דרך Redis או CDN, במיוחד עם ISR ב-Next.js. קיצרנו את זמן תגובת ה-API ב-60% באמצעות חיפוש אינדקסי ב-PostgreSQL.
כיצד להגדיר Fallback לשדות מקומיים
הגדרת לוקאליים ב-Payload CMS היא אובייקט localization ב-payload.config.ts. הגדירו defaultLocale ואפשרו fallback: true. אז בקשה לשפה ללא תרגום תחזיר את הערך מ-defaultLocale. דוגמת קונפיגורציה:
// payload.config.ts
export default buildConfig({
localization: {
locales: [
{
label: 'Русский',
code: 'ru',
},
{
label: 'English',
code: 'en',
},
{
label: 'Українська',
code: 'uk',
},
],
defaultLocale: 'ru',
fallback: true,
},
})שדות מקומיים מוגדרים נקודתית. זה נותן גמישות: לדוגמה, // payload.config.ts export default buildConfig({ localization: { locales: [ { label: 'Русский', code: 'ru' }, { label: 'English', code: 'en' }, { label: 'Українська', code: 'uk' }, ], defaultLocale: 'ru', fallback: true, }, }) נשאר משותף, בעוד featuredImage ו-title ניתנים לתרגום.
// collections/Posts.ts
fields: [
{
name: 'title',
type: 'text',
localized: true,
required: true,
},
{
name: 'content',
type: 'richText',
localized: true,
},
{
name: 'slug',
type: 'text',
localized: true,
unique: true,
},
{
name: 'featuredImage',
type: 'upload',
relationTo: 'media',
// НЕ localized
},
] כיצד לבקש תוכן בשפות שונות דרך API
בקשות REST פשוטות: richText מחזיר תרגומים באנגלית; // collections/Posts.ts fields: [ { name: 'title', type: 'text', localized: true, required: true, }, { name: 'content', type: 'richText', localized: true, }, { name: 'slug', type: 'text', localized: true, unique: true, }, { name: 'featuredImage', type: 'upload', relationTo: 'media', // НЕ localized }, ] מחזיר את כל הלוקאליים בבת אחת כאובייקט. ב-Next.js Server Component זה נראה כך:
// app/[locale]/posts/[slug]/page.tsx
import { getPayload } from 'payload'
import { notFound } from 'next/navigation'
type Locale = 'ru' | 'en' | 'uk'
export default async function PostPage({
params,
}: {
params: { locale: Locale; slug: string }
}) {
const payload = await getPayload({ config })
const result = await payload.find({
collection: 'posts',
locale: params.locale,
where: {
and: [
{ slug: { equals: params.slug } },
{ _status: { equals: 'published' } },
],
},
})
if (!result.docs[0]) notFound()
return <PostPage post={result.docs[0]} />
}
export async function generateStaticParams() {
const payload = await getPayload({ config })
const locales: Locale[] = ['ru', 'en', 'uk']
const params: { locale: Locale; slug: string }[] = []
for (const locale of locales) {
const posts = await payload.find({
collection: 'posts',
locale,
limit: 1000,
})
posts.docs.forEach(post => {
if (post.slug) params.push({ locale, slug: post.slug as string })
})
}
return params
}תבנית זו מספקת SSR, ISR, ויצירת דפים סטטיים לכל שפה. מתחת למכסה המנוע, Payload יוצר אינדקסים ב-PostgreSQL, ומאיץ שאילתות בסדר גודל.
למה Payload CMS יעיל יותר מ-Strapi ללוקליזציה
הטבלה שלהלן מציגה הבדלים מרכזיים. Payload משתמש באובייקטי JSONB ברמת השדה, ומספק זמני תגובה מתחת ל-50ms. Strapi יוצר רשומות נפרדות לכל שפה, מה שעלול להוביל לשאילתות N+1. Contentful מכריח לוקליזציה של כל השדות, ומפחית גמישות. Payload CMS עולה על Strapi במהירות שאילתות עד פי 10 וגמיש פי 3 מ-Contentful. עבור פרויקט טיפוסי עם 3 שפות, הלקוחות שלנו חוסכים בין $3,000 ל-$7,000 בעלויות פיתוח בהשוואה ל-Strapi.
| קריטריון | GET /api/posts?locale=en |
?locale=all |
// app/[locale]/posts/[slug]/page.tsx import { getPayload } from 'payload' import { notFound } from 'next/navigation' type Locale = 'ru' | 'en' | 'uk' export default async function PostPage({ params, }: { params: { locale: Locale; slug: string } }) { const payload = await getPayload({ config }) const result = await payload.find({ collection: 'posts', locale: params.locale, where: { and: [ { slug: { equals: params.slug } }, { _status: { equals: 'published' } }, ], }, }) if (!result.docs[0]) notFound() return <PostPage post={result.docs[0]} /> } export async function generateStaticParams() { const payload = await getPayload({ config }) const locales: Locale[] = ['ru', 'en', 'uk'] const params: { locale: Locale; slug: string }[] = [] for (const locale of locales) { const posts = await payload.find({ collection: 'posts', locale, limit: 1000 }) posts.docs.forEach(post => { if (post.slug) params.push({ locale, slug: post.slug as string }) }) } return params } |
|---|---|---|---|
| ארכיטקטורה | אובייקטי JSONB ברמת השדה | רשומות נפרדות לכל שפה | מרחבים נפרדים |
| Fallback | מובנה, ברמת הקונפיגורציה | דרך פלאגין או מותאם אישית | אין, רק דרך API |
| ביצועים | מילישניות (אינדקסי) | תלוי ב-N+1 | יציב, אך יקר |
| גמישות | לוקליזציה של כל שדה | רק שדות מסוג content-type | כל השדות מחויבים בלוקליזציה |
הודות לארכיטקטורה של Payload, אנו חוסכים עד 40% מזמן הפיתוח על לוקליזציה. 90% מהלקוחות שלנו מדווחים על שיפור ב-Core Web Vitals לאחר יישום אסטרטגיית הלוקליזציה שלנו.
תהליך העבודה
- ניתוח — קביעת רשימת השפות, הצורך ב-fallback, ואילו שדות ללוקליזציה.
- עיצוב — הגדרת
localizationבקונפיגורציה, מיגרציה של אוספים קיימים. - יישום — הוספת
localized: trueלשדות, כתיבת שאילתות מותאמות ל-Next.js. - בדיקות — אימות כל הלוקאליים ידנית ודרך בדיקות אוטומטיות, מדידת מדדי Core Web Vitals.
- פריסה — הגדרת DNS, CDN, Edge caching.
השוואת סוגי שאילתות ב-Payload
| סוג שאילתה | פרמטר | תוצאה | ביצועים |
|---|---|---|---|
| לוקאל יחיד | ?locale=en |
רק תרגום en | גבוהים עם cache |
| כל הלוקאליים | ?locale=all |
אובייקט של כל התרגומים | פחות שאילתות, יותר נתונים |
| Fallback | fallback: true |
החלפת DefaultLocale | תלוי בקונפיגורציה |
מה כלול בעבודה
- הגדרת לוקאליים ו-fallback ב-Payload CMS
- לוקליזציה של שדות נבחרים (text, richText, slug, select וכו')
- יצירת נקודות קצה API עם תמיכה בלוקאליים
- אינטגרציה עם Next.js App Router: ניתוב, SSR, ISR, יצירת דפים סטטיים
- בדיקות ותיקון באגים (hydration mismatch, כפילויות slug)
- תיעוד לתחזוקה והוספת שפות חדשות
- הדרכת מנהלי תוכן בפאנל הניהול של Payload
טעויות לוקליזציה נפוצות
בעיות נפוצות ופתרונותיהן
- כפילויות slug בעת לוקליזציה של slug — נפתר על ידי הגדרת
unique: trueוהתחשבות בלוקאל באינדקס. - Hydration mismatch ב-Next.js בעת מעבר שפה — נגרם ממצבים שונים בשרת ובקליינט. מטופל באמצעות
Suspenseוסנכרון i18n. - שאילתות איטיות עם
locale=all— עבור אוספים גדולים, עדיף להשתמש בנקודות קצה נפרדות ו-cache.
לוחות זמנים משוערים
הגדרת לוקליזציה לשלוש שפות עם התאמה של 5–10 אוספים ואינטגרציה עם Next.js — בין יום ליומיים. אם נדרשת מיגרציית נתונים מ-CMS קיים, לוח הזמנים גדל בשל ניתוח ו-ETL.
למה להפקיד לוקליזציה בידינו?
עם ניסיון של 5+ שנים ו-30+ פרויקטים רב-לשוניים מוצלחים, אנו מבטיחים לוקליזציה איכותית של Payload CMS. הניסיון שלנו כולל שילוב Redis caching, הגדרת מטא-דאטה SEO לכל שפה, ואופטימיזציה של LCP/CLS. אנו מבטיחים שהאתר שלכם יעבוד ביציבות בעת מעבר בין לוקאליים, ו-Core Web Vitals לא יירדו.
צרו קשר לקבלת ייעוץ על הקונפיגורציה שלכם. אנו נעריך את הפרויקט ונציע ארכיטקטורה אופטימלית.







