Skip to main content

التوطين المستمر دون نظام TMS

تنشر شيفرتك باستمرار؛ ويجب أن تُنشر ترجماتك باستمرار أيضاً. إليك كيفية أتمتة التوطين ضمن سير عمل التطوير.

ما هو التوطين المستمر؟

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

النهج التقليدي

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

1

يضيف المطوّر سلاسل جديدة إلى ملف الإعدادات المحلية المصدر

2

تُصدَّر السلاسل وتُرفع إلى منصة TMS

3

يُبلَّغ المترجمون ويبدؤون العمل

4

تُراجع الترجمات وتُعتمد

5

تُنزل الملفات المترجمة وتُدمج من جديد

6

تُشحن الميزة مع الترجمات (بعد أيام إلى أسابيع)

Days to weeks

النهج الأصلي داخل IDE

مع الترجمة الأصلية داخل IDE، يترجم المطوّر السلاسل كجزء من سير عمل البرمجة المعتاد. لا تصدير، لا رفع، لا انتظار — تحدث الترجمات في الجلسة نفسها التي يتم فيها التطوير.

1

يضيف المطوّر سلاسل جديدة إلى ملف الإعدادات المحلية المصدر

2

يطلب المطوّر من مساعده بالذكاء الاصطناعي ترجمة الملف

3

تُكتب الملفات المترجمة مباشرةً إلى المشروع

4

تُشحن الميزة مع الترجمات في الالتزام نفسه

Same commit

النهج التقليدي

6 steps

Multiple tools and platforms

Days to weeks per cycle

النهج الأصلي داخل IDE

4 steps

Inside your editor

Same commit

3

إعداد خط ترجمتك

بالنسبة إلى الفرق التي تريد ترجمة آلية تتجاوز IDE، أضف خطوة في CI/CD لترجمة السلاسل الجديدة أو المتغيرة مع كل push إلى main. يعمل ذلك مع GitHub Actions وGitLab CI أو أي نظام CI/CD.

ابدأ بالترجمة الأصلية داخل IDE للفرق الصغيرة. أضف أتمتة CI/CD عندما ينمو فريقك إلى أكثر من 3-4 مطورين أو عندما تحتاج إلى ضمان توفر الترجمات مع كل دمج إلى main.

أضِف الترجمة كخطوة ضمن مسار CI/CD الحالي لديك. تعمل الترجمة بعد نجاح البناء وقبل النشر، بما يضمن أن كل إصدار يتضمن ترجمات مُحدَّثة.
.github/workflows/translate.yml
# .github/workflows/translate.yml
name: Translate
on:
  push:
    branches: [main]
    paths: ['locales/en/**']

jobs:
  translate:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Translate changed strings
        run: |
          npx i18n-agent translate locales/en.json \
            --to de,ja,es,fr,ko,zh-Hans \
            --api-key ${{ secrets.I18N_AGENT_API_KEY }}

      - name: Commit translations
        run: |
          git config user.name "github-actions"
          git config user.email "[email protected]"
          git add locales/
          git diff --cached --quiet || git commit -m "chore: update translations"
          git push
.gitlab-ci.yml
# .gitlab-ci.yml
translate:
  stage: deploy
  only:
    changes:
      - locales/en/**
  script:
    - npx i18n-agent translate locales/en.json
        --to de,ja,es,fr --api-key $I18N_AGENT_API_KEY
    - git add locales/ && git commit -m "chore: translations" && git push
4

إضافة ضمان جودة الترجمة إلى CI

تلتقط الفحوص الآلية ضمن خط CI الترجمات المفقودة، وplaceholders المعطوبة، وصيغ رسائل ICU غير الصالحة قبل أن تصل إلى الإنتاج. هذه نصوص بسيطة تقارن ملف الإعدادات المحلية المصدر مع جميع الإعدادات المحلية المستهدفة.

من دون التحقق من الترجمات على مستوى CI، قد تصل الترجمات المفقودة إلى الإنتاج بصمت. يرى المستخدمون مفاتيح خاماً مثل "settings.title" أو سلاسل فارغة بدلاً من النص المترجم. فحص CI لمدة 5 دقائق يمنع ذلك بالكامل.
check-translations.sh
#!/bin/bash
# check-translations.sh — Run in CI to catch missing translations

SOURCE="locales/en.json"
LANGS=("de" "ja" "es" "fr")
EXIT_CODE=0

# Extract all keys from source
SOURCE_KEYS=$(jq -r '[paths(scalars)] | map(join(".")) | .[]' "$SOURCE" | sort)
SOURCE_COUNT=$(echo "$SOURCE_KEYS" | wc -l)

for lang in "${LANGS[@]}"; do
  TARGET="locales/$lang.json"
  if [ ! -f "$TARGET" ]; then
    echo "❌ Missing: $TARGET"
    EXIT_CODE=1
    continue
  fi

  TARGET_KEYS=$(jq -r '[paths(scalars)] | map(join(".")) | .[]' "$TARGET" | sort)
  MISSING=$(comm -23 <(echo "$SOURCE_KEYS") <(echo "$TARGET_KEYS"))

  if [ -n "$MISSING" ]; then
    COUNT=$(echo "$MISSING" | wc -l)
    echo "❌ $lang: $COUNT missing keys"
    echo "$MISSING" | head -5
    EXIT_CODE=1
  else
    echo "✅ $lang: all $SOURCE_COUNT keys present"
  fi
done

exit $EXIT_CODE
check-placeholders.sh
#!/bin/bash
# check-placeholders.sh — Validate placeholder consistency

SOURCE="locales/en.json"
LANGS=("de" "ja" "es")

for lang in "${LANGS[@]}"; do
  TARGET="locales/$lang.json"

  # Compare placeholders like {{name}}, {count}, %s, %d
  jq -r 'paths(scalars) as $p | [($p | join(".")), (getpath($p))]
    | @tsv' "$SOURCE" | while IFS=$'\t' read -r key value; do
    SOURCE_PH=$(echo "$value" | grep -oE '\{\{[^}]+\}\}|%[sd@]' | sort)
    TARGET_VAL=$(jq -r "getpath($(echo $key | jq -R 'split(".")'))" "$TARGET")
    TARGET_PH=$(echo "$TARGET_VAL" | grep -oE '\{\{[^}]+\}\}|%[sd@]' | sort)

    if [ "$SOURCE_PH" != "$TARGET_PH" ]; then
      echo "❌ $lang/$key: placeholder mismatch"
      echo "   Source: $SOURCE_PH"
      echo "   Target: $TARGET_PH"
    fi
  done
done

تحقّق من الترجمات في CI

أضف i18n-validate إلى خط CI لالتقاط المفاتيح المفقودة وplaceholders المعطوبة ومشكلات الجمع تلقائياً. استخدم i18n-pseudo لتوليد ترجمات مزيفة لاختبار التراجع البصري.
5

اكتشاف انجراف الترجمة والتعامل معه

يحدث انجراف الترجمة عندما تتغير السلاسل المصدرية ولا تُحدَّث الترجمات. تقول الإنجليزية "Save changes" بينما لا تزال الألمانية تعرض النص القديم. يقارن اكتشاف الانجراف الطوابع الزمنية للملفات أو تجزئات المحتوى.

الترجمات القديمة أسوأ من الترجمات المفقودة. الترجمة المفقودة خطؤها واضح — يرى المستخدم مفتاحاً أو لغة بديلة. أما الترجمة القديمة فتقول شيئاً خاطئاً بصورة مقنعة، ما قد يضلل المستخدمين أو يسبب مشكلات دعم.
detect-drift.sh
#!/bin/bash
# detect-drift.sh — Find stale translations

SOURCE="locales/en.json"
SOURCE_HASH=$(md5sum "$SOURCE" | cut -d' ' -f1)
HASH_FILE=".translation-hashes"

# Compare current source hash with stored hash
if [ -f "$HASH_FILE" ]; then
  STORED_HASH=$(grep "^en:" "$HASH_FILE" | cut -d: -f2)
  if [ "$SOURCE_HASH" != "$STORED_HASH" ]; then
    echo "⚠️  Source strings changed since last translation"
    echo "   Run translations to update all locales"

    # Show which keys changed
    git diff HEAD~1 "$SOURCE" | grep '^[+-]' | grep -v '^[+-][+-]'
  fi
fi

# Update stored hash
echo "en:$SOURCE_HASH" > "$HASH_FILE"
6

اختر نهج الترجمة المناسب لك

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

تتعامل ترجمة الذكاء الاصطناعي مع أكثر من 80% من سلاسل التطبيقات المعتادة بجودة إنتاجية. خصّص المترجمين البشريين للنصوص القانونية، وصوت العلامة التجارية، والمحتوى الحساس ثقافياً حيث تكون الدقة والظلال التعبيرية الأهم.
Cost Comparison
Translation Approach Comparison:

Content Type         | Approach          | Cost/word  | Quality
─────────────────────┼───────────────────┼────────────┼──────────
UI strings, labels   | AI/LLM            | $0.001-01  | Production
Tooltips, help text  | AI/LLM            | $0.001-01  | Production
Marketing copy       | AI + human review | $0.05-0.15 | High
Legal / compliance   | Human translator  | $0.15-0.40 | Certified
Brand voice content  | Human translator  | $0.20-0.50 | Premium
7

سير عمل Git للترجمات

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

تتسبب ملفات JSON الكبيرة الخاصة باللغات المحلية في تعارضات دمج متكررة عندما تُعدّلها فروع متعددة في الوقت نفسه. رتّب المفاتيح أبجديًا واستخدم مفتاحًا واحدًا لكل سطر لتقليل حجم الفروقات وتسهيل حل التعارضات.

توجد ملفات الترجمة في مستودعك جنبًا إلى جنب مع الشيفرة. تكون خاضعة للتحكم بالإصدارات، وقابلة للمراجعة ضمن pull requests، وتُنشر عبر المسار نفسه مثل كل شيء آخر.
.gitattributes + package.json
# .gitattributes — reduce merge conflicts in locale files
locales/*.json merge=union

# Sort keys alphabetically to minimize diffs:
# package.json script:
"sort-locales": "node -e \"
  const fs = require('fs');
  const f = process.argv[1];
  const d = JSON.parse(fs.readFileSync(f));
  const s = (o) => Object.keys(o).sort().reduce((r,k) =>
    ({...r, [k]: typeof o[k]==='object' ? s(o[k]) : o[k]}), {});
  fs.writeFileSync(f, JSON.stringify(s(d), null, 2)+'\\n');
\""

المزالق الشائعة

اعتبار التوطين خطوة لاحقة للتطوير

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

غياب التحقق من الترجمة على مستوى CI

من دون فحوصات آلية، تصل الترجمات المفقودة، والعناصر النائبة المعطوبة، والصيغ غير الصالحة إلى الإنتاج. أضِف التحقق من الاكتمال وصحة الصيغ إلى مسار CI لديك.

الإفراط في التعقيد باستخدام TMS

صُممت TMS لإدارة سير عمل المترجمين البشريين. إذا كنت تستخدم ترجمة AI، فقد لا تحتاج إلى العبء الإضافي الذي تفرضه TMS. ابدأ ببساطة — ترجِم داخل IDE أو ضمن CI/CD — وأضِف TMS فقط إذا احتجت إلى إدارة المترجمين البشريين.

عدم تتبع حداثة الترجمات

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

جرّب i18n Agent الآن

أفلت ملف الترجمة هنا

JSON, YAML, PO, XML, CSV, Markdown, Properties

أو انقر للاستعراض

اللغات المستهدفة

لا حاجة إلى التسجيلتقدير فوري

الأسئلة المتكررة