التدويل (i18n) في Rust: مكتبتا gettext-rs و fluent-rs

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة

التدويل (i18n) في Rust: gettext-rs و fluent-rs

\n\n

التدويل (i18n) هو جانب أساسي في تطوير التطبيقات الحديثة، حيث يسمح بتكييف البرمجيات للمستخدمين من مختلف البلدان والثقافات. في نظام Rust البيئي، توجد عدة مكتبات قوية لتنفيذ i18n. في هذه المقالة، سنستعرض اثنتين من الأكثر شيوعًا: gettext-rs (النهج الكلاسيكي القائم على gettext) و fluent-rs (نظام التوطين الحديث من Mozilla).

\n\n

1. مكتبة gettext-rs

\n\n

gettext-rs هي غلاف Rust لنظام GNU gettext الكلاسيكي. وهي مثالية للمشاريع التي تستخدم gettext بالفعل، أو لمن يفضلون الحلول المجربة عبر الزمن.

\n\n

التثبيت والإعداد

\n\n

أضف التبعية في Cargo.toml:

\n\n
[dependencies]\ngettext-rs = "0.7"\ngettext-sys = "0.21"
\n\n

مثال أساسي للاستخدام

\n\n
use gettextrs::*;\n\nfn main() {\n    // تعيين الإعدادات المحلية ومجال الترجمة\n    setlocale(LocaleCategory::LcAll, "ru_RU.UTF-8");\n    bindtextdomain("myapp", "/usr/share/locale").unwrap();\n    textdomain("myapp").unwrap();\n\n    // استخدام الترجمة\n    let greeting = gettext("Hello, world!");\n    println!("{}", greeting);\n\n    // الصيغ الجمعية\n    let items = 5;\n    let message = ngettext("{} item", "{} items", items);\n    println!("{}", message.replace("{}", &items.to_string()));\n}
\n\n

العمل مع السياق

\n\n

للتمييز بين السلاسل المتطابقة في سياقات مختلفة، استخدم pgettext:

\n\n
let menu_item = pgettext("menu", "File");\nlet dialog_title = pgettext("dialog", "File");
\n\n

2. مكتبة fluent-rs

\n\n

fluent-rs هي نظام توطين حديث ومرن وقوي، طورته Mozilla. وهي تدعم التراكيب النحوية المعقدة، الصيغ الجمعية، والترجمات السياقية.

\n\n

التثبيت

\n\n
[dependencies]\nfluent = "0.16"\nfluent-bundle = "0.15"\nfluent-resmgr = "0.5"\nfluent-langneg = "0.4"\nunic-langid = "0.9"
\n\n

إنشاء ملفات الترجمة (FTL)

\n\n

يستخدم Fluent تنسيق ملفات خاص به .ftl. مثال للغة العربية (ar.ftl):

\n\n
hello-world = مرحباً، أيها العالم!\ngreeting = أهلاً، {$name}!\nitems-count = { $count ->\n    [one] {$count} عنصر\n    [two] {$count} عنصرين\n    [few] {$count} عناصر\n    [many] {$count} عنصراً\n    *[other] {$count} عنصر\n}
\n\n

مثال لاستخدام fluent-rs

\n\n
use fluent_bundle::{FluentBundle, FluentResource};\nuse unic_langid::langid;\nuse std::fs;\n\nfn main() {\n    // تحميل ملف الترجمة\n    let ftl_string = fs::read_to_string("locales/ar.ftl")\n        .expect("فشل قراءة ملف التوطين");\n    let resource = FluentResource::try_new(ftl_string)\n        .expect("خطأ في تحليل FTL");\n\n    // إنشاء حزمة للغة العربية\n    let lang_ar = langid!("ar");\n    let mut bundle = FluentBundle::new(&[lang_ar]);\n    bundle.add_resource(&resource).unwrap();\n\n    // الحصول على الترجمة مع المعاملات\n    let mut errors = vec![];\n    let msg = bundle.get_message("greeting").unwrap();\n    let mut args = fluent_bundle::FluentArgs::new();\n    args.set("name", "أحمد");\n    let pattern = msg.value().unwrap();\n    let value = bundle.format_pattern(pattern, Some(&args), &mut errors);\n    println!("{}", value);\n\n    // الصيغ الجمعية\n    let msg = bundle.get_message("items-count").unwrap();\n    let mut args = fluent_bundle::FluentArgs::new();\n    args.set("count", 3);\n    let pattern = msg.value().unwrap();\n    let value = bundle.format_pattern(pattern, Some(&args), &mut errors);\n    println!("{}", value);\n}
\n\n

3. مقارنة بين gettext-rs و fluent-rs

\n\n

توصيات