← كل المقالات

تنظيم محتوى Astro متعدد اللغات بطريقة قابلة للصيانة

دليل عملي لتنظيم مقالات Astro والمسارات والقوالب والترجمات والبيانات الوصفية داخل Content Collections دون تكرار أو فوضى.

يبني بكري عبدالسلام مواقع الويب والتطبيقات والتكاملات ومنتجات ووردبريس، ويوثق مركز بكري التقني القرارات التقنية وراء هذا العمل.

الخلاصة

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

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

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

متى تحتاج إلى إعادة تنظيم المحتوى؟

لا تبدأ ببنية معقدة لموقع من ثلاث صفحات. أعد التنظيم عندما ترى واحدة أو أكثر من العلامات التالية:

  • حقول الواجهة الأمامية تختلف من مقال إلى آخر بلا سبب.
  • ملفات المسارات تحتوي HTML كبيراً أو منطقاً مكرراً بين العربية والإنجليزية.
  • زر تغيير اللغة يرسل القارئ إلى الصفحة الرئيسية بدلاً من المقال المقابل.
  • عنوان الصفحة أو الرابط الأساسي أو hreflang يُبنى بطريقة مختلفة في كل قالب.
  • لا يكتشف أمر البناء المقالات الناقصة أو الروابط المتصادمة.

هنا تصبح بنية المحتوى أداة تمنع الأخطاء، لا مجرد ترتيب أجمل للمجلدات.

ضع المقالات داخل مجموعة محتوى مكتوبة الأنواع

المقالات تتشارك حقولاً متوقعة مثل العنوان والوصف واللغة والتاريخ والتصنيف. لذلك تناسبها Content Collections في Astro:

const articles = defineCollection({
  loader: glob({
    base: './src/content/articles',
    pattern: '**/*.{md,mdx}',
  }),
  schema: z.object({
    title: z.string(),
    description: z.string(),
    locale: z.enum(['en', 'ar']),
    routeSlug: z.string(),
    translationKey: z.string(),
    publishedAt: z.coerce.date(),
    updatedAt: z.coerce.date().optional(),
    tags: z.array(z.string()).default([]),
    draft: z.boolean().default(false),
  }),
});

يفشل البناء عند نسيان حقل مطلوب أو كتابة قيمة لغة غير صحيحة. هذا أفضل من اكتشاف صفحة بلا وصف بعد النشر.

لا تنقل كل نص في الموقع إلى المجموعة. صفحات مثل «عني» و«تواصل» يمكن أن تبقى صفحات Astro أو مكونات مخصصة إذا لم تكن لها نسخ كثيرة. استخدم المجموعة للمحتوى الذي يتكرر ويحتاج إلى استعلام وفرز وربط.

افصل هوية المقال عن رابطه العام

من المفيد وجود حقلين منفصلين:

  • translationKey يربط النسختين العربية والإنجليزية للموضوع نفسه.
  • routeSlug يحدد الجزء الظاهر في الرابط.

قد يتغير عنوان المقال العربي أو رابطه لاحقاً، بينما تبقى علاقة الترجمة ثابتة. ولا تعتمد على اسم الملف وحده؛ معرّف المجموعة يجب أن يظل فريداً حتى عندما تشترك اللغتان في Slug واحدة تحت /blog/ و/ar/blog/.

نظم الملفات بصورة يفهمها المحرر سريعاً:

src/content/articles/
├── en/
│   └── astro-content-architecture.md
└── ar/
    └── astro-content-architecture.md

اجعل ملفات المسارات رفيعة

مسؤولية ملف المسار هي اختيار المقالات الصحيحة وإنشاء المسارات الثابتة وتمرير المقال إلى قالب القراءة:

---
import { getCollection } from 'astro:content';
import PostPage from '../../../components/PostPage.astro';

export async function getStaticPaths() {
  const entries = await getCollection(
    'articles',
    ({ data }) => data.locale === 'ar' && !data.draft,
  );

  return entries.map((article) => ({
    params: { slug: article.data.routeSlug },
    props: { article },
  }));
}

const { article } = Astro.props;
---

<PostPage article={article} />

لا تضع تصميم المقال وجدول المحتويات والبيانات المنظمة داخل ملف المسار. عندما يملك مكون واحد قالب القراءة، يصل إصلاح واحد إلى اللغتين من دون نسخ ولصق.

اجعل اللغة مدخلاً واضحاً

مرر locale إلى المكونات المشتركة بدلاً من فحص pathname في مواضع متفرقة. ومن قاموس واحد استخرج:

  • اتجاه الصفحة ltr أو rtl.
  • أسماء عناصر التنقل.
  • مسارات الصفحات في اللغة الحالية.
  • طريقة تنسيق التاريخ.
  • نصوص جدول المحتويات والمشاركة والمقال المرتبط.

يجب أن يضبط عنصر <html> قيمتي lang="ar" وdir="rtl". واستخدم خصائص CSS المنطقية مثل padding-inline وmargin-inline-start حتى يعمل القالب في الاتجاهين دون قائمة طويلة من الاستثناءات.

يشرح إنشاء موقع عربي وإنجليزي باستخدام Astro إعداد المسارات وhreflang واتجاه النص بالتفصيل.

اجمع البيانات الوصفية في القالب الأساسي

ينبغي أن يبني القالب الأساسي الرابط الأساسي canonical ووسوم Open Graph واكتشاف RSS والبيانات المشتركة. أما قالب المقال فيمرر العنوان والوصف وتاريخ النشر والتعديل وبيانات BlogPosting الخاصة بالمقال.

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

لا تربط ترجمتين لمجرد تشابه الرابط. ابحث عن النسخة المقابلة بواسطة translationKey، ولا تُخرج hreflang لصفحة غير موجودة.

أبقِ JavaScript اختيارياً

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

استخدم Astro Island فقط عندما توجد حالة تفاعلية تستحق كلفة JavaScript، ثم اختر توقيت التحميل الأقل اندفاعاً. وبعد الإضافة افحص حجم الحزمة الناتجة؛ قد يستدعي مكون صغير مكتبة أكبر من المحتوى نفسه.

لتحويل ذلك إلى حدود قابلة للقياس، راجع دليل ميزانية الأداء في Astro.

اختبر مسار النشر قبل إضافة المقالات

اجعل أمر البناء يفحص على الأقل:

  1. اكتمال الحقول المطلوبة وصحة اللغة والتاريخ.
  2. عدم تكرار (locale, routeSlug).
  3. وجود ترجمة واحدة فقط لكل مفتاح في كل لغة.
  4. عدم نشر المسودات في الصفحات أو RSS أو Sitemap.
  5. صحة الروابط الأساسية وبدائل اللغة.
  6. وجود عنوان ووصف فريدين لكل صفحة.
  7. سلامة الروابط الداخلية المهمة.

بعد البناء، افتح مثالاً من كل لغة ومن كل نوع صفحة. نجاح TypeScript لا يثبت أن جدولاً عريضاً أو مقطع كود سيظهر جيداً في RTL.

أخطاء شائعة

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

أسئلة شائعة

هل أستخدم ملف Markdown واحداً للغتين؟

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

هل يجب أن تكون روابط المقالات العربية بالعربية؟

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

هل Content Collections قاعدة بيانات؟

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

مراجع رسمية

لديك سؤال عن هذا الدليل أو فكرة لتعاون تقني؟ تواصل مع بكري عبر المركز التقني.

نهاية الملاحظة.