This page was machine-translated. Spotted a mistake?Help improve it.
Skip to content

دليل الترجمة

يأتي SnapOtter مزوّدًا بـ 21 لغة جاهزة للاستخدام. يستخدم نظام i18n وقت تشغيل مخصصًا خفيف الوزن مع اكتمال اللغات المفروض عبر TypeScript وتقسيم الشيفرة الديناميكي.

اللغات المدعومة

الرمزاللغةNative NameDirection
enالإنجليزيةEnglishLTR
zh-CNالصينية (المبسطة)简体中文LTR
zh-TWالصينية (التقليدية)繁體中文LTR
jaاليابانية日本語LTR
koالكورية한국어LTR
esالإسبانيةEspañolLTR
frالفرنسيةFrançaisLTR
itالإيطاليةItalianoLTR
pt-BRالبرتغالية (البرازيل)Português (Brasil)LTR
deالألمانيةDeutschLTR
nlالهولنديةNederlandsLTR
svالسويديةSvenskaLTR
ruالروسيةРусскийLTR
plالبولنديةPolskiLTR
ukالأوكرانيةУкраїнськаLTR
arالعربيةالعربيةRTL
trالتركيةTürkçeLTR
hiالهنديةहिन्दीLTR
viالفيتناميةTiếng ViệtLTR
idالإندونيسيةBahasa IndonesiaLTR
thالتايلانديةไทยLTR

كيف يعمل اكتشاف اللغة

يستخدم SnapOtter ترتيب حلٍّ من ثلاث طبقات:

  1. تفضيل المستخدم - مخزَّن في localStorage("snapotter-locale") ومتزامن مع إعدادات المستخدم عند تسجيل الدخول
  2. الاكتشاف التلقائي للمتصفح - يمرّ عبر مصفوفة navigator.languages مع مطابقة بادئة BCP 47
  3. الافتراضي للنسخة - متغيّر البيئة DEFAULT_LOCALE الخاص بالمشرف (يُجلَب من GET /api/v1/config/locale)
  4. الرجوع إلى الإنجليزية - متاح دائمًا

يمكن للمستخدمين تغيير اللغة من:

  • محدِّد الكرة الأرضية في التذييل (سطح المكتب، ظاهر دائمًا)
  • محدِّد اللغة في صفحة تسجيل الدخول (قبل المصادقة)
  • قسم الإعدادات > عام (تفضيل لكل مستخدم)
  • قائمة اللغة المنسدلة في الشريط الجانبي للجوال
  • قسم الإعدادات > النظام يحدّد الافتراضي على مستوى النسخة (للمشرف فقط)

كيف تعمل الترجمات

توجد جميع سلاسل واجهة المستخدم في packages/shared/src/i18n/. الملف المرجعي هو en.ts، الذي يصدّر كائنًا مُنمَّطًا يحتوي على كل سلسلة يستخدمها التطبيق (نحو 1500 مفتاح). اللغات الأخرى هي ملفات منفصلة (مثل de.ts و fr.ts) تصدّر البنية نفسها.

يستخدم النوع TranslationKeys الأداة DeepStringRecord لقبول أي قيمة سلسلة مع فرض بنية المفاتيح. يلتقط TypeScript المفاتيح المفقودة في أي ملف ترجمة في وقت التصريف.

يُحمَّل فقط الإعداد اللغوي النشط في وقت التشغيل عبر import() الديناميكي، مما يُبقي الحزمة الرئيسية صغيرة.

استخدام الترجمات في المكوّنات

tsx
import { useTranslation } from "@/contexts/i18n-context";
import { format, plural } from "@/lib/format";

function MyComponent() {
  const { t, locale, setLocale } = useTranslation();
  
  return (
    <div>
      <h1>{t.common.settings}</h1>
      <p>{format(t.settings.people.deleteConfirm, { username: "admin" })}</p>
      <p>{plural(count, t.automate.fileCount, t.automate.fileCountPlural)}</p>
    </div>
  );
}

المساهمة بترجمة

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

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

TIP

لا تتطلب طلبات سحب الترجمة موافقة مسبقة. انسخ المستودع (fork)، وأجرِ تغييراتك، وافتح طلب سحب. راجع دليل المساهمة لمعرفة عملية طلب السحب الكاملة ومتطلب CLA.

كيفية إنشاء ترجمة أو تحديثها

1. انسخ المستودع (fork) واستنسخه

bash
git clone https://github.com/<your-username>/snapotter.git
cd snapotter
pnpm install

2. انسخ الملف المرجعي (للغة جديدة فقط)

تخطَّ هذه الخطوة إذا كنت تحسّن ترجمة موجودة.

bash
cp packages/shared/src/i18n/en.ts packages/shared/src/i18n/XX.ts

3. ترجم السلاسل

افتح ملفك الجديد وترجم كل قيمة سلسلة. أبقِ بنية الكائن والمفاتيح كما هي تمامًا.

ts
import type { TranslationKeys } from "./en.js";

export const xx: TranslationKeys = {
  common: {
    upload: "Your translation here",
    // ... translate all entries
  },
  // ... translate all sections
} as const;

القواعد:

  • لا تترجم مفاتيح الكائن، بل القيم النصية فقط
  • أبقِ as const في النهاية
  • استورد TranslationKeys من ./en.js ونمّط تصديرك
  • أبقِ العناصر النائبة {variable} كما هي تمامًا
  • يجب أن تحتوي المصفوفات (rotatingPhrases و progressMessages) على العدد نفسه من المدخلات
  • لا تترجم: SnapOtter و JPEG و PNG و WebP و EXIF و API وغيرها من المصطلحات التقنية

4. سجّل الإعداد اللغوي (للغة جديدة فقط)

أضف إعدادك اللغوي إلى SUPPORTED_LOCALES في packages/shared/src/i18n/index.ts:

ts
{ code: "xx", name: "Language Name", nativeName: "Native Name", dir: "ltr" },

5. تحقّق

bash
pnpm typecheck    # catches missing or mistyped keys
pnpm lint         # formatting check
pnpm dev          # manually verify strings appear correctly

6. أرسل

افتح طلب سحب على main بعنوان مثل feat(i18n): add Swedish translation أو fix(i18n): correct German typos. سيطلب منك روبوت CLA التوقيع عند مساهمتك الأولى.

إضافة مفاتيح ترجمة جديدة

عند إضافة ميزة جديدة تحتاج إلى سلاسل واجهة مستخدم جديدة:

  1. أضف المفاتيح الجديدة إلى en.ts أولًا (الملف المرجعي)
  2. شغّل pnpm typecheck - سيفشل كل ملف إعداد لغوي إذا كان يفتقد المفتاح الجديد
  3. أضف المفتاح الجديد إلى جميع ملفات الإعداد اللغوي (استخدم الإنجليزية كخيار رجوع مؤقت)

الإعداد

حدّد لغة النسخة الافتراضية عبر متغيّر البيئة:

yaml
DEFAULT_LOCALE: "de"  # German as the default for all new users

مرجع الملفات

الملفالغرض
packages/shared/src/i18n/en.tsسلاسل الإنجليزية (الإعداد اللغوي المرجعي، نحو 1500 مفتاح)
packages/shared/src/i18n/index.tsSUPPORTED_LOCALES و loadTranslations() وتصديرات الأنواع
packages/shared/src/i18n/<locale>.tsملفات الترجمة لكل لغة
apps/web/src/contexts/i18n-context.tsxخطاف I18nProvider و useTranslation()
apps/web/src/lib/format.tsمساعدات format() و plural() و formatFileSize()
apps/api/src/routes/config.tsنقطة النهاية العامة GET /api/v1/config/locale

ترجمة الموقع الإلكتروني والوثائق ومرجع API

يغطي دعم الـ 21 لغة أعلاه التطبيق. الموقع العام (snapotter.com)، وموقع الوثائق هذا، ومرجع REST API مترجمة أيضًا إلى جميع الـ 21 لغة، بواسطة مسار منفصل مقيَّد بالتجزئة يعيد استخدام أسماء الأدوات وأوصافها نفسها من packages/shared/src/i18n، لذا تبقى المصطلحات متسقة في كل مكان.

مترجمة آليًا افتراضيًا

كل صفحة غير إنجليزية على الموقع والوثائق مترجمة آليًا في التمريرة الأولى (بواسطة جلسة Claude Code، وليس خدمة طرف ثالث) وتحمل شعارًا صغيرًا قابلًا للإغلاق يوضّح ذلك، مع رابط للعودة إلى هنا. هذا متعمَّد: فهو يشحن جميع الـ 21 لغة بسرعة وبصدق، ثم يدعو المجتمع إلى تحسين الصفحات الأهم. الترجمة الآلية توصّل المعنى؛ والمراجعة البشرية تجعله يُقرأ بشكل طبيعي.

كيف يقرّر المسار ما يترجمه

تُجزَّأ كل وحدة قابلة للترجمة من المصدر الإنجليزي، وتُخزَّن التجزئة بجوار ترجمتها. في كل تشغيل، يقوم المسار بما يلي:

  • يترجم أي وحدة ليس لها ترجمة بعد،
  • يتخطى أي وحدة لا يزال تجزئتها المخزَّنة يطابق المصدر الإنجليزي،
  • يعيد ترجمة وحدة آلية عندما يتغير مصدرها الإنجليزي،
  • ويضع علامة على وحدة بشرية مُنقَّحة بوسم stale (تحتاج مراجعة) عندما يتغير مصدرها الإنجليزي، بدلًا من الكتابة فوق عملك.

تنقيح ترجمة ويب عبر طلب سحب

تحسّن ترجمة موقع أو وثائق أو مرجع API بالطريقة نفسها التي تحسّن بها إعدادًا لغويًا للتطبيق: بتحرير الملف المُولَّد وفتح طلب سحب.

  1. اعثر على الترجمة المُولَّدة للغتك:
    • سلاسل واجهة الموقع: apps/landing/src/i18n/<locale>.json
    • صفحة وثائق: apps/docs/<locale>/**.md
    • مرجع API: apps/api/src/openapi.<locale>.yaml
  2. حرّر النص. أبقِ الشيفرة والروابط و {placeholders} وأي علامات ⸤I18N…⸥ كما هي تمامًا؛ فمُدقّق المسار يرفض أي ترجمة تُسقط هذه العناصر أو تعيد ترتيبها.
  3. افتح طلب سحب. يقلب تحرير الوحدة مصدرها من machine إلى human، لذا لن يكتب المسار فوقها أبدًا في تشغيل لاحق. إذا تغير المصدر الإنجليزي بعد ذلك، توضَع علامة على وحدتك بوسم stale للمراجعة بدلًا من استبدالها بصمت.

للإبلاغ عن ترجمة خاطئة دون تقديم شيفرة، افتح مشكلة على GitHub مع ذكر عنوان URL للصفحة واللغة والنص غير الصحيح وإصلاحك المقترح.

TIP

يشغّل المشرفون مسار الترجمة؛ لست بحاجة إلى مفتاح API للمساهمة. فقط حرّر الملف المُولَّد وافتح طلب سحب. راجع scripts/i18n/README.md لمعرفة كيفية تشغيل المسار.