اكتشاف المفاتيح الناقصة في ملفات ARB لتطبيق Flutter

آخر تحديث: · LocalePilot

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

مستعجل؟ افحص ملفات ARB مباشرة في متصفحك: مجانًا، دون تسجيل، ودون رفع أي ملف.

تذكير سريع: كيف تُنظَّم ملفات ARB

مع flutter gen-l10n، لكل لغة ملفها الخاص (app_en.arb وapp_fr.arb…). ملف القالب، المحدد بالخيار template-arb-file في l10n.yaml، هو المرجع: يحتوي على كل المفاتيح وبياناتها الوصفية @key (الوصف والمتغيرات).

{
  "cartCount": "{count, plural, =0{Empty cart} =1{1 item} other{{count} items}}",
  "@cartCount": {
    "placeholders": { "count": { "type": "int" } }
  }
}

1. دع Flutter يسرد الرسائل غير المترجمة

أضف الخيار untranslated-messages-file إلى l10n.yaml:

arb-dir: lib/l10n
template-arb-file: app_en.arb
untranslated-messages-file: untranslated.json

في كل عملية توليد، يكتب Flutter في هذا الملف مفاتيح القالب الناقصة في كل لغة. إنه أبسط فحص يمكن إعداده؛ تأكد أن الملف فارغ (أو لا يحتوي إلا على {}) قبل النشر.

2. قارن المفاتيح بسكربت Dart صغير

لفحص في CI يفشل برسالة واضحة، يكفي سكربت بسيط:

import 'dart:convert';
import 'dart:io';

void main() {
  final dir = Directory('lib/l10n');
  final template = _keys(File('lib/l10n/app_en.arb'));
  var failed = false;
  for (final file in dir.listSync().whereType<File>()) {
    if (!file.path.endsWith('.arb')) continue;
    final missing = template.difference(_keys(file));
    if (missing.isNotEmpty) {
      failed = true;
      print('${file.path}: ${missing.join(', ')}');
    }
  }
  if (failed) exit(1);
}

Set<String> _keys(File f) => (jsonDecode(f.readAsStringSync()) as Map<String, dynamic>)
    .keys
    .where((k) => !k.startsWith('@'))
    .toSet();

المفاتيح التي تبدأ بـ@ بيانات وصفية، لذا تُستبعد من المقارنة.

3. افحص المتغيرات

قد ينكسر مفتاح موجود في كل اللغات: إذا استخدمت الترجمة الفرنسية {nombre} بينما يعرّف القالب {count}، يضيف gen-l10n المتغير nombre معاملًا إضافيًا في كل اللغات، فيفشل تصريف مواضع الاستدعاء الحالية. وفي المقابل، تمر الترجمة التي حذفت متغيرًا ببساطة دون أي تحذير (التفاصيل في دليل صيغ الجمع والمتغيرات في ICU). قارن لكل مفتاح الأسماء الواردة بين الأقواس المعقوفة بتلك المعرّفة في @key.placeholders. وانتبه لرسائل ICU (plural وselect): الكلمات المفتاحية مثل other ليست متغيرات.

4. راقب القيم الفارغة أيضًا

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

قائمة التحقق قبل الإصدار

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

الأسئلة الشائعة

هل يبلّغ Flutter عن الترجمات الناقصة؟

نعم، إذا أضفت untranslated-messages-file إلى l10n.yaml: يكتب flutter gen-l10n في هذا الملف مفاتيح القالب الناقصة في كل لغة. ومن دونه لا تحصل إلا على تحذير موجز.

هل يجب نسخ بيانات @key الوصفية إلى كل لغة؟

لا. تُقرأ البيانات الوصفية (الوصف والمتغيرات) من ملف القالب؛ أما الملفات الأخرى فتكفيها الترجمات.

كيف أتجنب أسماء المتغيرات الخاطئة؟

قارن لكل مفتاح الأسماء الواردة بين الأقواس المعقوفة في الترجمة بتلك المعرّفة في القالب، واجعل CI يفشل عند وجود اختلاف.