אנגליה: השפה היא כמו שפת המערכת הקיימת, אנגלית. גרמניה: יש לכם מתרגם שיתרגם בקלות לגרמנית ומישהו בחברה שיודע ספרדית היטב. תוך כמה ימים אתם יוצרים אקסל עם כל הודעות המערכת למשמש (“user strings”) בכל 4 השפות.
סביבת הפיתוח מאפשרת ניהול מספר שפות ל User Strings (תהיה זו ג’אווה עם Resource Bundle property files או iOS עם NSLocalizedString).
האם זה יותר מעניין של כמה ימים – בכדי לכבוש את העולם המערבי המפותח? (פרגון לישראל)
אני כותב את הפוסט בהמשך להאזנה לפרק של מובייל ובירה ששמעתי לאחרונה – פודקאסט עברי מוצלח על פיתוח מובייל שאני שמח להמליץ עליו בהזדמנות זאת. אני שומע קבוע והוא עוזר לי להישאר בעניינים בנושאי פיתוח למובייל.
אחד מחברי הפודקאסט סיפר שאפליקציית מובייל שהם כתבו הצליחה באופן מפתיע בשוק הרוסי והשוק הסיני – והם החליטו לתרגם את האפליקציה לשפות אלו. אני מכיר את נושאי רב-הלשוניות (Multi-lingual) מעולם ה Enterprise, אך נראה שהוא רלוונטי למדי גם לאפליקציות מובייל.
נושא ריבוי-הלשונות הוא נושא לא-מורכב, אך עשוי להיות מעט מפתיע. נראה לי שהוא גם לא כ”כ מוכר. בבדיקה קצרה בגוגל לא מצאתי עליו חומר איכותי, לא ספרים ובטח לא חומר טוב בעברית.
אני אנסה לשנות זאת… 🙂
מושגים
בתחום זה יש 3 מושגים מבלבלים:
- Internationalization (בקיצור: i18n)
- Localization (בקיצור: l10n)
- Globalization (בקיצור: g11n)
המינוח Internationalization הוא דיי ארוך. מכיוון שאנשים מזהים מילים בעיקר בעזרת האות הפותחת והמסיימת, אפשר לקצר ל “i—n” ולשמור על היכולת של לקשר את הקיצור למילה המקורית. כמה אותיות יש באמצע? 18. לכן: i18n. (לא מאמינים? תספרו).
Internationalization הוא התהליך של הכנת התוכנה לריבוי שפות ואזורים (regions).
נהוג לקדד את ה Locale בעזרת שפה ע”פ תקן ISO 639-1 ואזור ע”פ תקן ISO 3166-1.
למשל: en_US (אנגלית, ארה”ב), en_GB (אנגלית, ארה”ב) או zh_CN (סינית בסין) או אפשר גם he_CN (עברית בסין).
חזרה ל FlappyWare
הכנסתם למערכת את כל משפטי הטקסט ב-3 השפות החדשות (גרמנית, צרפתית ועברית). אבל הלקוחות מתלוננים:
- הישראלים רוצים שכל התפריטים ועימודי הדף יהיו מימין לשמאל. העימוד הנוכחי פשוט לא מתאים!
אולי למתכנת, עימוד משמאל לימין לא מפריע (או עדיף), אך פועל במפעל, או אמא שיש לה מספיק נושאי-עניין בחיים – פשוט רוצים שהממשק יהיה קל ונוח (“למה לא עשו את זה בסדר? הם לא רואים שזה עקום?”). - הבריטים רוצים שהמערכת תשאל: “?what is your favourite colour” ולא “?what is your favorite color”. הבדל בין אנגלית-אמריקאית לאנגלית-בריטית, שנתפס אצל הבריטים כמאוד-לא-קטנוני.
- ישנם באגים לא צפויים במערכת בספרדית בתחום החיפוש. משום מה גם הטבלאות התחרבשו… מה זה קשור לתרגום?!
- הגרמנים פשוט לא מרוצים ונמנעים משימוש באפליקציה. לא הצלחתם לייצר איתם קשר טוב מספיק להבין מה בכלל הבעיה (?!).
כאשר המשתמשים שלכם מגיעים מתרבות שונה ודוברים שפה שונה, גם הטיפול בכל case/bug נהייה קשה יותר. כשלקוח טוען ש”בהונגרית זה צריך להיות ככה…”, ואתם לא מבינים על מה הוא מדבר / למה זה יצא אחרת – זה יכול להיות מאמץ לא קטן להבין ולתקן.
להבין את תהליך התרגום
לפני שנבחן “מה יכול להשתבש?” (זה החלק המשעשע), כדאי לדבר גם על תהליך התרגום, שגם הוא עשוי מעט להפתיע. בגדול, ניתן לחלק את מה שנרצה לתרגם ל 2 סוגים ב 2 קטגוריות.
הקטגוריות הן:
- תוכן מערכת – כל הודעות טקסט במסופקות כחלק מהאפליקציה: כותרות, תפריטים, הודעות שגיאה וכו’. סוג זה הוא הנפוץ ביותר.
- תוכן לקוח – תוכן שהלקוח יצר בעצמו והוא רוצה לתרגם. סוג זה של תוכן רלוונטי כנראה רק לתוכנה עסקית, ורק לחלק קטן ממנה. לדוגמה: מערכת שיווק אונליין הנמכרת ללקוח (קמעונאי כלשהו) רוצה למכור סחורה במדינות שונות – לכן עליו לתרגם את קטלוג המוצרים, כתבי אחריות, מפרטים וכו’ – תוכן שהוא יצר.
- מחרוזות (Strings), קרי “טקסט נטו” – אותן קל למדי לתרגם.
- כל סוג אחר של מדיה: תמונות, מסמכים (למשל PDF), קישורים וכו’.
תמונות (כמו ה screenshot ב appstore או כפתורים באפליקציה) לעתים מכילות טקסט – ועל כן יש גם ליצור להן עותק מתורגם. ייתכנו תמונות שונות ללוקאלים שונים, למשל תמונה שונה לשוק החרדי ולשוק החילוני בארץ (כן… ניתן לראות את השוק החרדי כסוג של Locale שונה, למרות שהוא במדינת ישראל).
לעתים אלו קישורים (URLs) לאתרים שונים, כאשר נקשר אתרים שונים לשפות / לוקאלים שונים.
אפילו אם המערכת שאותה נרצה לתרגם היא מערכת online (למשל ממשק וובי בענן), את התרגום נהוג לא לבצע בתוך המערכת אלא במערכות תרגום ייחודיות. למשל: במקרה של תרגום תוכן-לקוח, עשוי להראות סביר לספק את היכולת בתוך המערכת, הרי יש כבר ממשק ווב. מה יותר נוח מזה?!
לרוב זה לא יהיה נוח מ 2 סיבות:
א. למתרגם לא תמיד תהיה גישה למערכת ה Online.
ב. כלי התרגום מספקים יתרונות משמעותיים (למשל מילון-מונחים שכבר בשימוש במערכת, Thesaurus ועוד) – והמתרגמים עשויים דווקא לגבות מחיר גבוה יותר על שימוש במערכת אונליין.
בעיניים עצומות
פרט קטן לגבי התרגום לא ציינתי: המתרגמים לרוב עושים את עבודתם ללא שהם מכירים לעומק את האפליקציה שהם מתרגמים.
“לעומק”? תנו לי לתקן: הרבה פעמים הם מעולם לא ראו אותה או לא אפילו לא יודעים מהי.
רוצים להימנע מתרגום נוסח Google Translate או תרגומים מביכים כגון “רפידת הטקסט” (TextPad)? – אם כן, כדאי שתעזרו למתרגמים.
מתרגמים קצת יותר רציניים יבקשו מסמך המתאר את האפליקציה, הסיטואציה והמשתמשים – או יקבעו פגישה כדי ללמוד ולכתוב כזה בעצמם למתרגמים האחרים. המתרגמים יכולים לעבוד בכל העולם ותרגום מחרוזות האפליקציה שלכם (אם היא לא גדולה) יכולה להיות אפליקציה אחת מתוך ארבעה שהם מתרגמים באותו היום. במיוחד כאשר מדובר בעדכוני-גרסה, ולא תוכנה שעוברת תרגום בפעם הראשונה.
עם מסמכים בפורמטים שונים (Pdf, תמונות, תמונות וקטוריות וכו’) – המתרגמים יכולים להסתבך, ולשלוח לקבלן משנה בעל הבנה פחותה יותר במה מדובר. איך תאמדו את איכות התוצאה?
מה שעושים בדרך כלל (כשרוצים תוצאות יותר טובות) הוא מפרקים את הטקסטים מתוך קבצי המדיה השונים ושולחים אותם כ Strings. משאירים את הטיפול בפורמטים השונים של קבצי המדיה in-house.
אם המערכת שלכם מספקת יכולת לתרגם תוכן-לקוח – זה אומר לאפשר להוסיף מחרוזות שלא נמצאות במערכת.
דבר שני וחשוב יותר הוא הוספת תיאור קצר שמספק את ההקשר לכל מחרוזת. לדוגמה על “Hall of Fame” ניתן לציין שזוהי כותרת מסך עם תוצאות המשחק הטובות ביותר או דף באתר האינטרנט המאתר את מורשת החברה. התרגום – יהיה שונה ע”פ ההקשר שיסופק.
את ההערות מוסיפים פעמים רבות המתכנתים תוך כדי שהם כותבים את הקוד. כל מחרוזת שהיא טקסט לתרגום (לא כל המחרוזות בתוכנה הן כאלו, כמובן) – מתווספת עם הערה. יש סביבות בהן מוסיפים את ההערות בקוד (iOS?) וכאלו שבעזרת כלים נלווים ב IDE (למשל בג’אווה).
אחרי שמסיימים פרויקט תרגום, נראה הגיוני מאוד לסמן את המחרוזות למשתמש (“User Strings”) בפרויקט הבא מהיום הראשון, כך שלא יהיה צריך לעבור מחרוזת-מחרוזת בקוד ולאתר את כל הטקסטים למשתמש. כך גם הומלץ בפרק של “מובייל ובירה” שעסק בנושא.
מניסיוני, אפשר לעשות זאת אם כלי הפיתוח באמת נוחים. Localization הוא קצת מעבר ל User Strings ולא כדאי להתחיל להשקיע לפני שברור שזו המטרה.
את המחרוזות לתרגום, נוהגים לנהל באחד מ-2 פורמטים נפוצים:
PO/POT – שמקובל בעולם ה Unix. מערכת WordPress, למשל משתמשת בו.
XLIFF – מקובל יותר בעולם הג’אווה / אנטרפרייז. אפשר להמיר בקלות קבצי properties שמייצר Eclipse ל XLIFF.
עוד בסיס מידע חשוב הוא ה Translation Memory, מין “בסיס נתונים” (קובץ TMX או TBX) של המונחים בהם השתמשו במערכת. כאשר מתרגם יקבל מכם עוד עבודה אחרי חצי שנה שלא נגע במערכת (כאילו שהוא זוכר אותה) – ה Translation Memory יזכירו לו באלו מונחים הוא השתמש בעבר והוא יוכל לשמור על קונסיסטנטיות.
כדי שהמתרגמים יוכלו להיות עקביים, גם עליכם להיות עקביים במונחים בהם אתם משתמשים בשפת ה Master Language, כמובן.
כיצד נראה התרגום בקוד
זה כמובן תלוי בשפת וסביבת הפיתוח. אני אצמד לדוגמאות ב Java – השפה בה אני מכיר את הנושא בצורה הטובה ביותר.
בג’אווה יש מנגנון בשם Resource Bundles שעוזר לנהל user strings בשפות שונות.
את ה Resource Bundle ניתן לייצר בעזרת Wizard ב Eclipse:
באותו הרגע נוצרים הקבצים הבאים:
- קובץ plugin.properties שכולל את טקסטי ברירת-המחדל / ה Master Language.
- לכל שפה, אזור או צימוד של השניים שהגדרנו – ייווצר קובץ נוסף, לדוגמה plugin_en.properties או plugin_en_GB.properties.
לאחר מכן ניתן לערוך את קבצי ה properties, כאשר כל key מייצג מחרוזת בכל שפה.
הערה: אצלנו בחברה היה Editor אחר, אולי פרי פיתוח פנימי. אנא סלחו אם אני מפספס פה איזה פרט.
בזמן ריצה של הקוד ישלוף את המחרוזת המתורגמת המתאימה:
שימו לב שלג’אווה יש מנגנון fallback אם הוא לא מוצא את הלוקאל המדויק:
אם למשל הלוקאל הוא “en_US” אך אין קובץ כזה, הוא ינסה להשתמש ב “en”. אם אין גם קובץ כזה – הוא ילך לקובץ ברירת המחדל (למשל: plugin.properties).
מה יכול להשתבש ב Localization? – מיון
נתחיל בכך שמתודת ()compareTo של המחלקה String בג’אווה עלולה כבר לגרום לטעות, אפילו בשפה האנגלית.
מדוע? בגלל הקידוד (להלן כמה יסודות שחשובים בכדי להבין).
בגדול, כל מחרוזת טקסט היא חסרת משמעות – אלא אם ידוע הקידוד שלה. הקידוד הוא כמו מפתח שמסביר כיצד לקרוא את המחרוזת. אם השתמשתם בקידוד שגוי, אתם עשויים לראות במקום טקסט – רצף של קשקושים או ריבועים חלולים (שמשמעם ב”חלונות”: אות שהייתה תקלה בפענוח שלה ולא יודעים כיצד לפענח).
הקידוד הבסיסי ביותר הוא קידוד בשם ASCII:
ASCII הוא קידוד 7-ביט. כלומר: כל אות יכולה להיות אחת מתוך 128 סימנים או אותיות.
32 התווים הראשונים הם control characters: טאב, רווח, מחיקה ועוד סימנים שרובם חסרי משמעות גרפית (למשל: סוף שורה). שאר התווים הם מספרים, אותיות וכמה סימני-שפה.
ישנן הרחבות לASCII של 8-ביט המוסיפות עוד כ 128 תווים המותאמים לשפות נוספות (כל הרחבה – לשפה אחרת). כלומר כל סימן/אות (character) הוא בית אחד / 8-ביט.

מיון בסיסי בשפת ג’אווה (וברוב השפות האחרות) מתבסס על הערך המספרי של האותיות במחרוזת.
כפי שניתן לראות, הערך המספרי של האות “Z” (גדולה) הוא 90, בעוד שהערך של “a” (קטנה) הוא גבוה יותר (97) – ולכן מיון יסדר מחרוזות בסדר הבא:
- Ant
- Zoo
- ambulance
- בשוודית, ישנה אות הנכתבת כ ae (או סימן æ) – מקומה בסדר הלקסיקוגרפי הוא אחרי האות “z”.
- בגרמנית, כאשר האות s מופיעה ברצף פעמיים – מקצרים את הצמד לכתיבת ß (כמו ביטא). סידור ע”פ ערכי ASCII ימיין את המילה groß (שקול ל gross = “גדול”) לאחר המילה grost – מכיוון שערך ה ASCII של ß גדול יותר. זו כמובן טעות צורמת לדובר גרמנית.
- ע”פ חוקי הדקדוק של שפות אירופאיות שונות, אותיות מוטעמות (“accent”) צריכות לבוא אחרי אותיות דומות לא מוטעמות. צרפתית גרועה אפילו יותר: אות מוטעמת מאוחרת היא חזקה יותר, כלומר: יש לבדוק את האותיות המוטעמות מימין לשמאל.
אפשר לנסות ללמוד את כל הבעיות בכל השפות השונות – ולממש אלגוריתם מיון, אך לא כדאי.
אפשר להשתמש בכלי קיים להתמודד עם בעיות ה internationalization – וזה מה שאמליץ לעשות.
ג’אווה, כבר מגרסאות מוקדמות, כללה סט כלים עשיר ל i18n, רובם תחת החבילה java.text.
במשך השנים, התחזוקה והעדכון של ספריות אלו מעט הוזנח וכיום הן נחשבות עדיין טובות – אך לא “state of the art”.
אם נושא ה i18n חשוב לכם באמת – הייתי ממליץ להשתמש בספריית ICU של IBM – ספריית open source בג’אווה (יש גם גרסת ++C) ל g11n המתוחזקת ברמה טובה.
יש גם רשימה של ספריות ג’אווהסקריפט לתמיכה ב i18n – אולם אין לי ניסיון עמן ואני לא יודע להמליץ.
בג`אווה, הביטוי הבא יבצע השוואה נכונה, ע”פ השפה הנתונה:
ל ICU יש גרסה משלה ל Collator – מדויקת יותר.
סיכום
טוב, כיסינו רק את נושא המיון – אך יש עוד מספר מקרים שכדאי להתייחס אליהם (חיפוש, עיבוד מחרוזות, html וכו’) אותם אני מקווה לכסות בפוסט המשך.
התאמה של אפליקציה לשפות אחרות (“ריבוי-לשונות”) היא לא רק “כאב ראש” ו”סיבוך נוסף” – זוהי הזדמנות להגיע לפלח שוק גדול בהרבה, מבלי להוסיף למערכת הרבה פיצ’רים. בעוד אנשי מקצוע מסוימים (למשל: מתכנתים) “מחויבים” לשלוט בשפה האנגלית, עובדים במגזרים שונים ואנשים פרטיים – לא זקוקים לכך. מעבר לכך: הם יכולים לשלוט באנגלית, אך עדיין לרצות תוכנה בשפה שלהם.
ריבוי-לשונות עשוי להיות פיצ’ר מכניס מאוד למערכת שכבר הוכיחה את עצמה.
כמובן שיש לתהליך globalization מלא יש עלות, במיוחד אם מתחילים לעשות שינויים בקוד (עבור חיפוש, מיון וכו’). כדאי להכיר את הנושאים ולהשתמש בפוסט(ים) כ reference לאלו בעיות יכולות לצוץ, ולבחור ע”פ מצב השוק – כמה רחוק ללכת.
שיהיה בהצלחה!
סקירה מקיפה על פורמטים וכלים על תרגום (אם המערכת שלכם תנהל תרגום): http://edutechwiki.unige.ch/en/Software_localization
התרגומיה, בלוג עברי על תרגום :http://yaeltranslation.com
אני חרדי, מסכים איתך לגבי Locale . . .