سؤال

أريد ترجمة برنامج كتبته بالفعل..إنه كبير إلى حد ما (حوالي 50 ألف سطر) ومن الناحية المثالية أريد نظامًا يسمح لي (كمبرمج) بالقيام بأقل قدر ممكن من العمل، وبدون تغييرات كبيرة في البرنامج - إن أمكن لا شيء على الإطلاق.

لقد نظرت إلى gettext() وأعجبني كثيرًا، لكن من غير الواضح بالنسبة لي كيف ستترجم سلاسل مثل هذه:

const char *Colors[] = {
 { "Red" },
 { "Blue" },
 { "Yellow" },
 ....
};

و هو جداً عادي في برنامجي..من الواضح أن استبدال "Red" بـ gettext("Red") لن ينجح.

لذلك اعتقدت أنني سأفعل شيئًا مثل OutputFunction(gettext(Colors[Id])))، ولكن كيف يمكنني الحصول على قائمة من السلاسل لترجمتها؟أشك في أن أي برنامج ذكي بما يكفي ليتمكن من الحصول على "الأحمر" و"الأزرق" و"الأصفر" من ذلك في قائمة الترجمة بشكل ثابت.

نظرًا لأنه خادم في الأساس، ليست هناك حاجة للقدرة على تغيير اللغة دون إعادة الترجمة (يمكنني تجميعه لكل لغة مدعومة دون أي مشكلة أو إزعاج كبير)، فكرت في constexpr الخاص بـ C++0x، والذي سيكون مثاليًا!سيعمل في المصفوفات/إلخ وسأحصل بسهولة على قائمة بالسلاسل لتوطينها في وقت الترجمة ..من المؤسف أنه لم ينفذه أي مترجم حتى الآن.

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

لذا، أي أفكار؟:/

هل كانت مفيدة؟

المحلول 2

بعد الكثير من اللعب باستخدام gettext() وxgettext، أعتقد أنني وجدت طريقة بنفسي (آسف واحدًا تلو الآخر ولكني لم يعجبني أسلوبك..يجب أن يكون هناك مئات من المصفوفات من هذا القبيل وسيتعين علي استيرادها جميعًا في main()، وهذا يتطلب الكثير من العمل الخارجي والكثير من العمل الإضافي :/).

على أي حال، أعتقد أن هذه هي الطريقة التي أعتقد أنه يمكن القيام بها من الناحية النظرية (لم أحاول بعد الترجمة فعليًا ولكني لا أرى سبب عدم نجاحها)

تعريفان:

#define _ gettext
#define __(x) x

ثم تستخدم _ للترجمة الفعلية و__ لوضع علامة على السلاسل على أنها "تتم ترجمتها":

const char *Colors[] = {
 { __("Red") },
 { __("Blue") },
 { __("Yellow") },
 ....
};

void PrintColor(int id) {
    cout << _("The color is: ") << _(Colors[id]);
}

ثم تقوم بتشغيل:

xgettext -k_ -k__ *.cpp

وستحصل على ملف .po التالي:

#: test.cpp:2
msgid "Red"
msgstr ""

#: test.cpp:3
msgid "Blue"
msgstr ""

#: test.cpp:4
msgid "Yellow"
msgstr ""

#: test.cpp:9
msgid "The color is: "
msgstr ""

لذلك، يمكنك استخدام __ (أو أي اسم آخر، لا يهم حقًا) كـ "دالة وهمية" للسماح فقط com.xgettext أعلم أن السلسلة تحتاج إلى الترجمة، و_ لاستدعاء gettext() فعليًا.

إذا اتصلت بـ _ باستخدام سلسلة، فسيتم وضع علامة على السلسلة ليتم ترجمتها أيضًا، إذا قمت باستدعائها باستخدام متغير أو مصفوفة أو أي شيء، فيبدو أن xgettext يتجاهلها ببساطة.

عظيم!الآن كل ما علي فعله هو مراجعة 5 تريليون ملف وإضافة الشرطة السفلية حولها، كما لو كنت قردًا :/

نصائح أخرى

بالنسبة لمثالك المحدد، قد أحاول شيئًا مثل:

// presumably globals
const char *Colors_en[] = {
 { "Red" },
 { "Blue" },
 { "Yellow" },
 ....
};
const char *Colors[] = {0};

// in main()
gettextarray(Colors_en, Colors, sizeof(Colors_en) / sizeof(char*));

يستدعي gettextarray gettext على كل إدخال ويكتب المخرجات.أعتقد أنه يمكن تنفيذه كمكالمة لـ std::transform.ويمكنك تجنب معلمة الحجم مع القليل من خداع القالب.

هناك خيار آخر يتمثل في استدعاء gettext عند النقطة التي يكون فيها أي من سلاسل الألوان على وشك الاستخدام (المعروضة أو الملحقة بسلسلة للعرض).هذا يعني تغيير المزيد من التعليمات البرمجية، لكنه لا يتطلب أن يقوم main() بترجمة كل مجموعة من السلاسل في البرنامج قبل القيام بأي شيء قد يستخدمها.

إذا كنت لا ترغب في القيام بالعمل بشكل رئيسي، فيمكنك القيام بذلك في الكود الذي يستخدم السلاسل، شيء من هذا القبيل:

if (Colors[0] == 0)
  gettextarray(Colors_en, Colors, sizeof(Colors_en) / sizeof(char*));

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

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top