BookTranslator
BookTranslator

איך לתרגם קובץ שפה JSON בלי לשבור מפתחות או מצייני מקום

ראו אילו ערכים בקובץ en.json מתורגמים, מה מתרגם קבצים משכתב (הערות, סדר מפתחות, מזהים ארוכים), ואיך לבדוק מצייני מקום, צורות רבים של ICU ומפתחות עם סקריפט חינמי וקובץ בדיקה.

BookTranslator

BookTranslator Team

קריאה של 11 דקות

כדי לתרגם קובץ שפה JSON כמו en.json, יש למסור את הקובץ כולו למתרגם שמבין JSON. הדבקת הטקסט הגולמי לחלון צ'אט או למתרגם אתרים היא הדרך המסוכנת לעשות זאת. מתרגם שמבין JSON קורא את הקובץ, מתרגם רק את ערכי הטקסט וכותב את אותם המפתחות בחזרה, כך שהאפליקציה שלכם עדיין יכולה לטעון את הקובץ. העתקה והדבקה עלולות לתרגם מפתח, לשנות סימן ציטוט או להשמיט סוגר מסולסל. כל אחד מאלה שובר את הקובץ.

שמירה על המפתחות היא החלק הקל. רוב הצרות מגיעות אחר כך: מציין מקום {name} שחוזר בתור {nom}, הודעת רבים של ICU שמאבדת את מקרה ה-other, כתובת URL שנשלחת לתרגום כמו כל טקסט אחר, וכמה שינויים שהמתרגם מבצע בקובץ עצמו. על אלה מדריך זה.

בנינו קובץ בדיקה עם כל אחד מהמקרים האלה וכתבנו בודק חינמי שמשווה קובץ מקור עם התרגום שלו. הרצנו גם את קובץ הבדיקה דרך עותק מקומי של קוד ניתוח וכתיבת ה-JSON שבו משתמש BookTranslator, עם סמן במקום מודל, כך שתוכלו לראות בדיוק אילו ערכים נשלחים ואיך הקובץ חוזר.

תשובה מהירה: מה קורה לכל חלק בקובץ

חלק בקובץדוגמה מהבדיקה שלנומה BookTranslator עושהמה לבדוק
מפתחות"greeting", "error"נשמרים כפי שהםשום דבר
ערכי טקסט רגיל"Reading list"מתורגמיםמשמעות, אורך על המסך
ערכים עם מצייני מקום"Welcome back, {name}!", "Saved %s of %d chapters"מתורגמים, מצייני המקום נכללים בטקסט הנשלחשמות מצייני מקום ומספרם (הבודק עושה זאת)
הודעות רבים של ICU"{count, plural, one {# book} other {# books}}"נשלחות כמחרוזת אחתמקרה ה-other, וקטגוריות רבים עבור שפת היעד
HTML מוטבע"accept the <b>Terms</b>."מתורגם; מספר התגיות נבדק לאחר התרגוםשמות תגיות וספירות (הבודק עושה זאת)
כתובות URL המאוחסנות כטקסט"https://example.com/help"נשלח לתרגוםשהוא חזר ללא שינוי
ערכים ללא אותיות"2.4.1", "—", ""הושארו כפי שהיוכלום
מספרים, true/false, null20, trueהושארו כפי שהיומזהים גדולים מאוד (ראו להלן)
מערכים של מחרוזות["Open", "Save", "Export as EPUB"]מתורגמים בקובץ המתורגם; נשארים ללא תרגום בקובץ הדו-לשוניהקובץ הדו-לשוני, אם אתם משתמשים בו
הערות (JSONC)// Shown on the home screenהוסרו. אם ערך מכיל גם //, הקובץ עלול להיכשל בטעינההסירו הערות לפני ההעלאה

המשך המדריך מראה מהיכן מגיע כל שורה ומה לעשות בנידון.

שלב 1: בדקו את קובץ המקור לפני ההעלאה

הריצו את הבודק על הקובץ שאתם מתכננים לתרגם. הוא דורש Python 3 ותו לא:

python3 check_i18n_json.py en.json

בקובץ הבדיקה שלנו הוא הדפיס:

WARN  limits.projectId: 9007199254740993 is above 2^53 and can change in a JavaScript round trip; store IDs as strings
WARN  error.network: a flat key with dots and a nested key resolve to the same dot path; tools that address strings by dot path can mix them up
INFO  (root): 3 keys look like integers; JavaScript sorts those first and in numeric order when it rewrites the object
INFO  source: 17 strings, 2 numbers

שתי האזהרות וההערה על מפתחות דמויי-מספר שלם תואמות כל אחת שינוי שראינו כשקובץ הבדיקה שלנו עבר דרך המתרגם. אם הקובץ שלכם לא מקבל אף אחת מהן, אפשר לדלג לשלב 3.

הבודק גם דוחה קובץ שאינו JSON קפדני, כגון כזה עם הערות או פסיקים עוקבים, כי זו הבעיה הבאה.

מה חזר מקובץ הבדיקה שלנו

הבדיקה רצה ב-2 בנובמבר 2026, כנגד הטיפול הנוכחי ב-JSON בצד השרת של BookTranslator. במקום לקרוא למודל, הבדיקה החליפה כל ערך שהיה נשלח לתרגום ב-[ZH] בתוספת הטקסט המקורי. כך התוצאה צפויה: כל דבר עם [ZH] לפניו נשלח, כל דבר בלעדיו לא נשלח. שתי הפלטים פורסמו: הקובץ המתורגם והקובץ הדו-לשוני.

הקובץ המתורגם

כל מפתח חזר ללא שינוי, והקובץ עדיין נפרס כראוי. מחרוזות שהכילו אותיות נשלחו, כולל {name}, %s, הודעת ICU, התג <b> וכתובת העזרה. מחרוזת הגרסה "2.4.1", המקף והמחרוזת הריקה לא נשלחו, מכיוון שאינם מכילים אותיות. מספרים ובוליאנים לא נגעו בהם.

ארבעה דברים נוספים השתנו:

  1. מחרוזת אחת נכנסה למפתח הלא נכון. בבדיקה שלנו, הקובץ הכיל מפתח שטוח "error.network" עם הטקסט "Check your connection." וגם מפתח מקונן "error": { "network": "Network error" }. המתרגם מזהה כל מחרוזת לפי הנתיב שלה עם נקודות בין החלקים, כך שלשתי המחרוזות הייתה אותה כתובת, error.network. בפלט, שני המפתחות הכילו את התרגום של "Network error". "Check your connection." נעלם. זה מצריך ששני הסגנונות יופיעו באותו קובץ, דבר נדיר, אבל זה נכשל בשקט. הבודק מזהיר מפני זה לפני ההעלאה.
  2. מפתחות דמויי מספרים שלמים סודרו מחדש. "steps": { "10": ..., "2": ..., "1": ... } חזר כ-"1", "2", "10". JavaScript תמיד מציגה מפתחות דמויי מספרים שלמים תחילה, בסדר מספרי, כשהיא בונה מחדש אובייקט. המפתחות והערכים עדיין תואמים, כך שהאפליקציה שלך בסדר, אבל diff מול קובץ המקור יהיה רועש.
  3. מזהה גדול איבד דיוק. 9007199254740993 חזר כ-9007199254740992. JavaScript מאחסנת מספרים כנקודה צפה של 64 סיביות, ומספרים שלמים מעל 2^53 לא כולם ניתנים לייצוג מדויק (MDN על Number.MAX_SAFE_INTEGER). אחסן מזהים ארוכים כמחרוזות, או הרחק אותם מקובץ השפה.
  4. העיצוב נכתב מחדש. הפלט משתמש בהזחה של שני רווחים ומסתיים בשורה חדשה. אם המקור שלך השתמש בטאבים או בארבעה רווחים, צפה לשינויים ברווחים ב-diff.

לקובץ הבדיקה שלנו לא היו מפתחות כפולים, אבל כדאי לדעת עליהם: מנתח ה-JSON של JavaScript שומר רק את הערך האחרון עבור מפתח חוזר, כך שהטקסט המוקדם יותר לעולם לא מתורגם. האפליקציה שלך תטען את אותו ערך אחרון, כך ששום דבר גלוי לא נשבר, אבל הבודק מציג מפתחות כפולים כדי שתוכל לנקות אותם.

הקובץ הדו-לשוני

הקובץ הדו-לשוני שומר על כל ערך מקורי ומוסיף מפתח אחים עם _translated בסוף:

"greeting": "Welcome back, {name}!",
"greeting_translated": "[ZH] Welcome back, {name}!",

זה עובד היטב לסקירה, מכיוון שהמקור והתרגום יושבים זה לצד זה. זה לא קובץ שהאפליקציה שלך יכולה לטעון, מכיוון שלכל מפתח יש כעת תאום. השתמש בקובץ המתורגם באפליקציה שלך.

פער אחד: מחרוזות בתוך מערכים לא מקבלות אח _translated, מכיוון שלפריטי מערך אין מפתח להוסיף לו. בבדיקה שלנו, "menu": ["Open", "Save", "Export as EPUB"] חזר באנגלית בקובץ הדו-לשוני, אבל מתורגם בקובץ המתורגם. אם אתה סוקר מהקובץ הדו-לשוני, בדוק מערכים בקובץ המתורגם.

קבצים עם הערות

פרויקטים רבים שומרים הערות בקבצי השפה שלהם (JSONC), דבר ש-JSON קפדני אינו מאפשר. המתרגם מנסה תחילה JSON קפדני. אם זה נכשל, הוא מסיר הערות ופסיקים עוקבים ומנסה שוב. הסרת הערות פירושה מחיקת כל מה שאחרי // בשורה, וזה כולל את ה-// ב-https://.

הקובץ שלנו עם הערה וכתובת URL לא נטען כלל; הניתוח נכשל בהערה הראשונה. קובץ עם הערות אך ללא // בתוך אף ערך נטען כשורה, וההערות הוסרו מהפלט.

אז: אם בקובץ שלך יש הערות, הסר אותן לפני ההעלאה, או שמור עותק עם ההערות וקבל את העובדה שהתרגום לא יכלול אותן.

שלב 2: הכנת הקובץ

אתה יכול לתקן את רוב הבעיות הללו לפני התרגום:

  • הפוך אותו ל-JSON קפדני. הסר הערות ופסיקים עוקבים. אם כלי הבנייה שלך קורא JSONC, שמור את הקובץ עם ההערות כמקור וייצא עותק נקי לתרגום.
  • השתמש בסגנון מפתח אחד. או קנן מפתחות או שטח אותם עם נקודות, לא שניהם באותו קובץ. אם אתה משתמש ב-i18next, אפשרות keySeparator שולטת באופן קריאת הנקודות במפתחות, אז בדוק את ההגדרה הזו לפני שאתה משטח משהו.
  • הוצא נתונים שאינם טקסט. מזהים, כתובות URL, דגלי תכונות ומגבלות שייכים לקונפיגורציה, לא לקובץ השפה. אם כתובת URL חייבת להישאר, השאר אותה, אבל צפה לבדוק אותה לאחר התרגום. המדריך שלנו לדברים שאין לתרגם מכסה כיצד להחליט מה עוד צריך להישאר בשפת המקור.
  • כתוב מצייני מקום באותו אופן בכל מקום. סגנון אחד, כגון {name}, קל יותר לבדיקה מאשר שילוב של {name}, {{name}} ו-%s.

שלב 3: תרגום הקובץ כולו

העלה את הקובץ הנקי למתרגם המסמכים של BookTranslator, שמציג .json עם שאר פורמטי הלוקליזציה והטקסט המובנה שהוא מקבל. המחיר מוצג לפני התשלום. כשהמשימה מסתיימת, עמוד ההיסטוריה שלך מציע את הקובץ המתורגם ואת הקובץ הדו-לשוני כהורדות נפרדות.

שני דברים באופן שבו הטקסט מתורגם משפיעים על התוצאה:

  • המודל לא רואה את המפתחות שלך. כל ערך נשלח כמקטע ממוספר, בלי שם המפתח. אם "button.open" ו-"status.open" שניהם אומרים "Open", למודל אין דרך לדעת שאחד הוא פועל והשני שם תואר. מחרוזות קצרות ועמומות הן אלה שכדאי לבדוק ידנית.
  • כל ערך מתורגם בנפרד. שום דבר לא מקשר בין שני מפתחות, כך שאותה מילה בשני מקומות יכולה לחזור בשתי דרכים שונות, ומילה שזקוקה לשני תרגומים שונים יכולה לחזור זהה. המילון האוטומטי האופציונלי של BookTranslator אוסף שמות, מקומות ומונחים מקצועיים ושומר על עקביות, אבל אינך יכול לתת לו תרגומים קבועים משלך. עבור מונחים שחייבים להיות מתורגמים בדרך אחת מדויקת, שמור רשימת מונחים ובדוק את המחרוזות האלה לאחר התרגום; מדריך המילון שלנו מסביר כיצד לתכנן אחד.

תגי HTML מוטבעים נספרים לאחר התרגום, ומקטע שהתגים שלו אינם תואמים נשלח שוב. מצייני מקום בסוגריים מסולסלים, מצייני מקום בסגנון %s ותחביר ICU נשלחים כחלק מהטקסט אך אינם נבדקים באותה צורה. הרץ את שלב 4 על כל תרגום.

אם אתה מעדיף לתרגם עם מודל צ'אט או מודל מקומי, שלח רק את הערכים, לעולם לא את הקובץ הגולמי, והחזר אותם למקומם לפי מפתח עם סקריפט. הבדיקות שלהלן חלות בכל מקרה.

שלב 4: בדיקת הקובץ המתורגם

השווה את התרגום למקור:

python3 check_i18n_json.py en.json fr.json

כדי להראות מה זה תופס, הכנו קובץ צרפתי עם שגיאות מושתלות. הוא עשוי ביד, לא פלט מודל. לאחר אותן אזהרות מקור כמו בשלב 1, הבודק הדפיס:

ERROR app.greeting: placeholders differ; lost ['name'] extra ['nom']
ERROR app.help_url: urls differ; lost ['https://example.com/help'] extra ['https://example.com/aide']
ERROR app.items: ICU message has no 'other' case
ERROR app.legacy: placeholders differ; lost ['%d'] extra []
ERROR limits.maxFiles: type changed from int to str
ERROR limits.projectId: non-text value changed: 9007199254740993 -> 9007199254740992
INFO  menu[1]: identical to source: 'Save'
INFO  compared 20 source values, 1 unchanged strings

כל אחד מאלה יופיע כבאג באפליקציה: שם ריק, קישור שבור, קריסה או הודעה גולמית כאשר רבים מוצג, ספירת פרקים חסרה, מגבלה המושווית כטקסט. שורת ה-INFO מפרטת מחרוזות שחזרו ללא שינוי. חלקן בסדר, כמו שמות מותגים; "Save" בתפריט צרפתי אינו.

הבודק משווה מפתחות, סוגי ערכים, ערכים שאינם טקסט, מצייני מקום ({name}, {{name}}, %s, %1$s, %@), שמות ארגומנטים של ICU, תגי HTML וכתובות URL. הוא אינו שופט את התרגום עצמו.

צורות רבים אמורות להשתנות

צורת רבים של ICU מפרטת הודעה אחת לכל קטגוריית רבים. לאנגלית יש שתי קטגוריות, one ו-other, אך לשפות רבות יש קבוצה שונה. תרגום רוסי טוב של הודעת ה-items שלנו ישתמש בדרך כלל ב-one, few, many ו-other, ותרגום יפני רק ב-other. לכן אי-התאמה כאן אינה תמיד שגיאה.

הקטגוריות מגיעות מכללי הרבים של Unicode CLDR, ו-other היא זו שיש בכל שפה. אלה הקטגוריות הקרדינליות שמדווחות על ידי Intl.PluralRules ב-Node.js עם CLDR 48:

שפהקטגוריות רבים
אנגלית, גרמניתone, other
צרפתית, ספרדית, פורטוגזיתone, many, other
רוסית, פולניתone, few, many, other
ערביתzero, one, two, few, many, other
יפנית, סינית, קוריאניתאחר

צרפתית, ספרדית ופורטוגזית משתמשות ב־many רק עבור מספרים עגולים גדולים מאוד, כמו מיליון, כך שהודעה עבור ספירות קטנות יכולה בדרך כלל להסתדר בלעדיו. הבודק מדווח על other חסר כשגיאה, ועל כל שינוי אחר בקטגוריות כאזהרה שיש להשוות לטבלה הזו. אפשר להדפיס את הרשימה עבור כל שפה בעצמכם:

node -e 'console.log(new Intl.PluralRules("ru").resolvedOptions().pluralCategories)'

המתרגם מקבל את המקרים באנגלית, לכן בדקו מה חזר. אם הודעה ברוסית או בערבית עדיין מכילה רק one ו־other, הוסיפו את המקרים החסרים ידנית, או בקשו מתרגם לעשות זאת.

לאחר מכן טענו אותו באפליקציה

הבודק מוכיח שהקובץ בטוח לטעינה, לא שהוא נקרא היטב. החליפו את האפליקציה לשפה החדשה והסתכלו על המסכים: מילים ארוכות בגרמנית או בפינית שגולשות מכפתור, טקסט מימין לשמאל בערבית או בעברית, ותאריכים או מספרים שהקוד שלכם מעצב בנפרד מקובץ השפה. המדריך שלנו לתרגום לעומת לוקליזציה מכסה מה עוד משתנה בין שווקים מלבד המילים.

בעיות נפוצות

הקובץ המתורגם לא נטען באפליקציה שלי. הריצו עליו את הבודק. אם הבודק לא מצליח לנתח אותו, הקובץ נערך לאחר התרגום או שלא היה תקין מלכתחילה. אם הוא מנותח, חפשו שורות ERROR בנוגע למפתחות או לסוגים.

מחרוזת מופיעה כהודעת ICU גולמית, כמו {count, plural, ...}. תחביר ה־ICU נשבר בתרגום, בדרך כלל סוגר מסולסל חסר או מקרה other חסר. העתיקו את המבנה מהמקור ותרגמו רק את המילים שבתוך כל מקרה.

הקובץ שלי הוא YAML, קובץ .po או Markdown. BookTranslator מקבל גם אותם, אבל לכל פורמט יש כללים משלו. לתיעוד, ראו את מדריך תרגום Markdown שלנו; עבור דפי אינטרנט, את מדריך קובץ HTML.

האם אפשר לתרגם רק את המפתחות החדשים? לא בתוך העלאה אחת; הקובץ כולו מתורגם. שימו את המפתחות החדשים בקובץ נפרד, תרגמו אותו, ומזגו את התוצאה לפי מפתח. הבודק יאשר שלקובץ הממוזג יש כל מפתח.

האם לתרגם את המפתחות? לא. מפתחות הם מזהים שהקוד שלכם מחפש. רק הערכים הם טקסט שאנשים קוראים.

פוסטים קשורים

איך לתרגם קובץ שפה JSON בלי לשבור מפתחות או מצייני מקום