بناء منصة حاسبات متعددة اللغات باستخدام Next.js 15

تحليل شامل لكيفية بناء منصة حاسبات متعددة اللغات عالية الأداء باستخدام Next.js 15 و React 19 و next-intl، بما في ذلك تطبيق التدويل وتحسين SEO والأداء.

6 دقيقة قراءة
Next.jsReactالتدويلSEOتحسين الأداءTypeScript

مرحباً أيها المطورون الزملاء! 👋

إذا كنت قد حاولت من قبل إنشاء موقع ويب يحتاج إلى العمل لمستخدمين حول العالم، فأنت تعرف مدى التحدي الذي يمكن أن يكون عليه هذا الأمر. لقد انطلقت مؤخراً في رحلة لإنشاء Free Calculators - منصة تخدم المستخدمين بـ 12 لغة مختلفة، ودعني أخبرك، لقد كانت مغامرة حقيقية!

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

لماذا بنينا هذا (ولماذا يهم)

تخيل هذا: أنت تبني تطبيق حاسبة. بسيط جداً، أليس كذلك؟ ولكن بعد ذلك تدرك أن شخصاً في اليابان قد يحتاج إليه باليابانية، وشخص في البرازيل قد يفضل البرتغالية، ومستخدموك الألمان يريدون بالتأكيد تنسيق أرقامهم بالطريقة الألمانية (1.234,56 بدلاً من 1,234.56). فجأة، حاسبتك البسيطة تصبح مشروعاً دولياً معقداً.

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

قرارات المكدس التقني: لماذا اخترنا هذه الأدوات

لماذا Next.js 15؟

لأكون صادقاً، عندما صدر Next.js 15 لأول مرة، كنا مترددين قليلاً. بعد كل شيء، "إذا لم يكن مكسوراً، لا تصلحه"، أليس كذلك؟ ولكن عندما رأينا App Router الجديد وتكامل React 19، قررنا القفز. اتضح أنه كان خياراً حكيماً.

// هكذا أعددنا التوجيه لدينا
export const routing = defineRouting({
  locales: [
    'en',
    'zh',
    'ja',
    'ko',
    'fr',
    'de',
    'es',
    'pt',
    'ru',
    'ar',
    'hi',
    'it',
  ],
  defaultLocale: 'en',
  localePrefix: 'as-needed', // هذا الإعداد وفر علينا الكثير من الصداع
  localeDetection: true,
});

React 19: هل يستحق الترقية؟

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

TypeScript: منقذنا

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

// هكذا نحدد أنواع الترجمة لدينا
interface TranslationKeys {
  nav: {
    siteName: string;
    home: string;
    calculators: string;
  };
  common: {
    calculate: string;
    clear: string;
    result: string;
  };
}

تنفيذ التدويل: التحديات الحقيقية والحلول

التحدي 1: تعقيد اكتشاف اللغة

قد تعتقد، "اكتشاف اللغة؟ سهل!" ولكن ليس كذلك. قد يصل المستخدمون من أجهزة مختلفة، أو يستخدمون VPN، أو لديهم تفضيلات لغة محددة. قضينا وقتاً طويلاً في إتقان منطق اكتشاف اللغة لدينا.

// إعداد middleware الخاص بنا
import createMiddleware from 'next-intl/middleware';
import { routing } from '@/i18n/routing';

export default createMiddleware(routing);

export const config = {
  matcher: '/((?!api|trpc|_next|_vercel|.*\\..*).*)',
};

التحدي 2: إدارة ملفات الترجمة

إدارة ملفات الترجمة لـ 12 لغة مثل إدارة 12 مشروع مختلف. طورنا بعض سكريبتات الأتمتة لمساعدتنا:

// سكريبت إدارة الترجمة لدينا
const addMissingTranslations = async () => {
  const baseTranslations = await loadTranslations('en');
  const allLocales = await getAllLocales();

  for (const locale of allLocales) {
    const existingTranslations = await loadTranslations(locale);
    const missingKeys = findMissingKeys(baseTranslations, existingTranslations);

    if (missingKeys.length > 0) {
      console.log(`Missing keys in ${locale}:`, missingKeys);
      await addMissingKeys(locale, missingKeys);
    }
  }
};

التحدي 3: فخ تنسيق الأرقام

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

تحسين SEO: جعل محركات البحث تحبنا

قوة توليد الموقع الثابت

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

// توليد صفحات ثابتة لكل لغة
export const dynamic = 'force-static';

export function generateStaticParams() {
  return routing.locales
    .filter(locale => locale !== routing.defaultLocale)
    .map(locale => ({ locale }));
}

فن توليد البيانات الوصفية

توليد البيانات الوصفية الصحيحة لكل لغة يتطلب بعض المهارة. طورنا نظاماً لتوليد بيانات وصفية صديقة لمحركات البحث تلقائياً:

export async function generateMetadata({
  params,
}: {
  params: Promise<{ locale: string }>;
}): Promise<Metadata> {
  const { locale } = await params;
  const t = await getTranslations({ locale, namespace: 'Home' });

  return {
    title: t('title'),
    description: t('description'),
    openGraph: {
      title: t('title'),
      description: t('description'),
      locale: locale,
    },
  };
}

تحسين الأداء: جعل تجربة المستخدم سلسة

أهمية تحسين الصور

قضينا وقتاً طويلاً في تحسين تحميل الصور. اعتماد تنسيقات AVIF و WebP حسّن سرعات تحميل صفحاتنا بنسبة 40%.

// إعداد الصور في next.config.ts
images: {
  formats: ['image/avif', 'image/webp'],
  domains: ['freecalculators.app'],
  deviceSizes: [640, 750, 828, 1080, 1200, 1920, 2048, 3840],
  imageSizes: [16, 32, 48, 64, 96, 128, 256, 384],
}

استراتيجية التخزين المؤقت: سلاحنا السري

تنفيذ استراتيجية التخزين المؤقت الصحيحة تطلب بعض التجربة والخطأ. انتهينا بمنهج تخزين مؤقت متعدد الطبقات:

async headers() {
  return [
    // تخزين مؤقت قوي للموارد الثابتة
    {
      source: '/(.*).(js|css|png|jpg|jpeg|gif|svg|ico|woff|woff2|ttf|eot)',
      headers: [{
        key: 'Cache-Control',
        value: 'public, max-age=31536000, immutable',
      }],
    },
    // تخزين مؤقت متفق عليه للصفحات
    {
      source: '/(.*)',
      headers: [{
        key: 'Cache-Control',
        value: 'public, max-age=0, must-revalidate',
      }],
    },
  ];
}

تصميم تجربة المستخدم: جعل الجميع يشعرون بالترحيب

تحدي التصميم المتجاوب

ضمان أن حاسباتنا تعمل بشكل مثالي على جميع الأجهزة هو تحدي مستمر. اعتمدنا منهج mobile-first:

// تخطيط متجاوب mobile-first
<div className="flex flex-col md:flex-row gap-4">
  <div className="w-full md:w-1/2">
    {/* واجهة الحاسبة */}
  </div>
  <div className="w-full md:w-1/2">
    {/* عرض النتائج */}
  </div>
</div>

إمكانية الوصول: أكثر من مجرد امتثال

أدركنا أن إمكانية الوصول ليست مجرد متطلب قانوني - إنه الشيء الصحيح. أضفنا تسميات ARIA مناسبة لكل عنصر تفاعلي:

<button
  aria-label={t('common.calculate')}
  aria-describedby="calculator-help"
  className="bg-blue-600 text-white px-4 py-2 rounded"
>
  {t('common.calculate')}
</button>

سلسلة أدوات التطوير: جعل التطوير أكثر كفاءة

مراقبة الأخطاء: شبكة الأمان لدينا

دمجنا Sentry لمراقبة الأخطاء، مما ساعدنا على اكتشاف العديد من المشاكل التي لم نتوقعها أبداً:

export default withSentryConfig(withNextIntl(nextConfig), {
  org: 'my-projects-pd',
  project: 'free-calculators',
  widenClientFileUpload: true,
  disableLogger: true,
  automaticVercelMonitors: true,
});

إدارة الترجمة المؤتمتة

طورنا بعض السكريبتات لإدارة ملفات الترجمة، وهذه السكريبتات أصبحت الآن جزءاً لا يتجزأ من سير عملنا.

الدروس التي تعلمناها

1. فكر في التدويل من البداية

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

2. تجربة المستخدم تفوق الاستعراض التقني

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

3. الأتمتة هي المفتاح

إدارة الترجمات يدوياً لـ 12 لغة غير واقعية. سكريبتات الأتمتة هي شريان الحياة لمشروعنا.

4. اختبر، اختبر، واختبر مرة أخرى

اللغات المختلفة لها أطوال نصوص مختلفة، وتنسيقات أرقام مختلفة، وتوقعات ثقافية مختلفة. الاختبار الشامل ضروري.

الخطط المستقبلية

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

الخلاصة

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

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


رابط المشروع: https://www.freecalculators.app المكدس التقني: Next.js 15, React 19, TypeScript, Tailwind CSS, next-intl