על תמיכה בלוקליזציה ב־C++‎ ועל תקן שבור

ב־7.10.2009, מאת ארתיום; פורסם תחת: תכנה חופשית, פיתוח, תכנה ומחשבים, C++‎‏, Unicode; ‏0 תגובות

ככל שעובד הזמן אנחנו מתקרבים יותר ויותר לתקן C++‎ החדש שבהחלט מעשיר את השפה בהרבה כלים חיוניים -- הן מבחינת ליבת השפה והן לבחינת הספריה הסטנדרטית.

אבל נשאר מקום אחד שבו C++0x כמעט ולא נגע, אפילו שהתקן שבור לחלוטין -- לוקליזציה...

לצורך הדגמה בואו נכתוב תכנה טרוייואלית שמדפיסה מספר לקובץ טקסט number.txt:

#include <iostream>
#include <fstream>
#include <locale>


int main()
{
        // Set global locale to system default;
        std::locale::global(std::locale(""));

        // open file "number.txt"
        std::ofstream number("number.txt");

        // write a number to file and close it
        number<<13456<<std::endl;
}

תכנה פשוטה אפילו טריוויאלית. עכשיו בואו נעשה אותו דבר ב־C.

#include <stdio.h>
#include <locale.h>

int main()
{
        setlocale(LC_ALL,"");
        FILE *f=fopen("number.txt","w");
        fprintf(f,"%'i\n",13456);
        fclose(f);
        return 0;
}

גם פשוט ביותר.

בואו נריץ את התכנות כאשר הלוקל הוא en_US.UTF-8... ונקבל בקובץ number.txt את המספר: 13,456, עכשיו נעשה אותו דבר, רק נגדיר לוקל נפוץ אחר ru_RU.UTF-8‏: כך LC_ALL=ru_RU.UTF-8 ./a.out ונקבל:

 ‎13<?>456

כאשר אם נריץ תכנה ב־C נקבל דווקא משהו נכון: ‎13 456

אופס... מה קרה כאן? כשאני עושה את אותו הדבר דרך C ודרך C++‎ אני מקבל תוצאה שונה, יותר מזה, הפלט של תכנה שכתובה ב־C++‎ מצביעה על טקסט UTF-8 לא תקין! (אפשר לבדוק בקלות עם iconv).

מה בעצם קראה כאן?

לפי הגדרות הלוקל הרוסי. התו שמפריד בין אלפים ומאות הוא תו U2002 -- ‏ EN SPACE -- סוג של רווח שונה מרווח ASCII רגיל U0020. כלומר בגלל שמדובר בתו Unicode שהוא לא בתחום ASCII הוא צריך להיות מקודד כמחרוזת ארוכה מבית 1.

אז למה ספריית C מתמודדת יפה מאוד עם בעיה זו וספריית C++‎ לא?

עכשיו בואו נסתכל בהגדרות הסביבה להצגת מספרים: המחלקה ‏std::numpunct מייצגת את סימון ההפרדה thousands_sep‏ כבית בודד! לכן אין שום סיכוי לייצג תו Unicode U2002, לעומת זאת, ספריית C, מייצגת את סימון ההפרדה כמחרוזת ולא כתו בודד. מכאן, אין שום בעיה לייצר מספרים.

זאת הייתה דוגמה של בעיוה הטריוויאלית לשחזור. קיימים עוד בעיות עקרוניות רבות כאלה בתקן לוקליזציה הקיים ב־C++‎ היום. חבל שהוועדה שמטפלת ב־C++0x כלל לא התייחסת לנושא זה --- אולי הגיע זמן להעלות את הנושא?

הוסף תגובה:

 
 כתובת דוא"ל לא תוצג
 

ניתן לכתוב תגובות עם שימוש בתחביר Markdown.

חובה לאפשר JavaScript כדי להגיב.

דפים

נושאים