מדריך בינאום ל־Java: תרגום קובצי .properties מבוסס בינה מלאכותית
הגדירו את ResourceBundle, ארגנו קובצי .properties, תרגמו ליותר מ־40 שפות באמצעות בינה מלאכותית, ולאחר מכן תנו ל־PTC (Private Translation Cloud) לסקור את אפליקציית ה־Java בזמן ריצה באמצעות צילומי מסך או תוסף דפדפן. בסוף התהליך יהיה לכם JAR רב-לשוני מוכן לשחרור, כשכל שפת יעד מאומתת לפני השחרור. לסקירה כללית של שירות ה־Java העצמאי, ראו תרגום אפליקציות Java מבוסס בינה מלאכותית.
ResourceBundle טוען את קובץ ה־.properties הנכון בזמן ריצה
מערכת הבינאום של Java בנויה סביב שני דברים. קובצי .properties שמאחסנים את המחרוזות המתורגמות שלכם, והמחלקה ResourceBundle שטוענת את הקובץ הנכון בזמן ריצה על סמך ה־locale של המשתמש.
כשהאפליקציה שלכם רצה, ResourceBundle בודק את ה־locale של המשתמש וטוען את הקובץ התואם באופן אוטומטי. אם חסר תרגום, הוא עובר לחלופה של קובץ ברירת המחדל בשקט. שום דבר לא מפסיק לעבוד, אך תרגומים חסרים גם לא מופיעים כשגיאות. קריאה למחרוזת בקוד:
ResourceBundle bundle = ResourceBundle.getBundle("messages", Locale.FRENCH);
String greeting = bundle.getString("welcome.message");
זהו כל המנגנון. שאר עבודת הלוקליזציה מתבצעת בקובצי ה־.properties עצמם, ולכן יש חשיבות לארגון נכון שלהם.
הגדירו את חבילת המשאבים שלכם עם messages_{locale}.properties
חבילת משאבים היא אוסף של קובצי .properties שחולקים שם בסיס משותף. שם הבסיס הוא החלק בשם הקובץ שלפני סיומת ה־locale. זהו השם שבו ResourceBundle.getBundle() משתמש כדי למצוא את הקובץ הנכון בזמן ריצה.
src/main/resources/
messages.properties # default (usually English)
messages_fr.properties # French
messages_de.properties # German
messages_es.properties # Spanish
messages_ja.properties # Japanese
messages_zh_CN.properties # Simplified Chinese (note underscore, not hyphen)
אפליקציות גדולות יותר משתמשות לרוב במספר חבילות משאבים כדי לשמור על סדר:
src/main/resources/
messages.properties
errors.properties
emails.properties
Java מצפה לתבנית שמות ספציפית: basename_language.properties, או basename_language_COUNTRY.properties עבור וריאנטים אזוריים:
messages_fr.properties # French
messages_fr_CA.properties # French (Canada)
messages_pt_BR.properties # Portuguese (Brazil)
קודי השפות פועלים לפי ISO 639-1. קודי המדינות פועלים לפי ISO 3166-1. שימוש בפורמט שגוי פירושו ש־ResourceBundle לא ימצא את הקובץ בזמן ריצה.
טענו והשתמשו בחבילה בקוד, עם MessageFormat להחלפת מצייני מיקום:
import java.util.Locale;
import java.util.ResourceBundle;
import java.text.MessageFormat;
public class App {
public static void main(String[] args) {
Locale locale = Locale.of("es");
ResourceBundle messages = ResourceBundle.getBundle("messages", locale);
String welcome = MessageFormat.format(
messages.getString("app.welcome"),
"My App"
);
System.out.println(welcome);
// -> "Bienvenido a My App"
}
}
עבור מחרוזות פשוטות ללא מצייני מיקום, messages.getString("key") מספיק.
שש מוסכמות שהופכות את קובצי ה־.properties שלכם למוכנים לתרגום
כל שורה היא צמד של מפתח־ערך המופרד על ידי =. האופן שבו אתם כותבים את קובץ המקור שלכם משפיע ישירות על איכות התרגומים שלכם. הדבר נכון בין אם אתם מתרגמים באופן ידני ובין אם באמצעות כלי בינה מלאכותית כמו PTC.
1. השתמשו במפתחות ברורים ותיאוריים שמציינים היכן המחרוזת מופיעה
המפתחות צריכים להבהיר היכן וכיצד נעשה שימוש במחרוזת. יש לכך חשיבות כשאתם מנהלים מאות מחרוזות על פני מספר קבצים.
# Incorrect
btn1 = Submit
msg2 = Error
# Correct
form.submit.button = Submit
error.login.invalid_credentials = Invalid username or password
לעולם אל תשנו מפתח לאחר שהתרגום התחיל. שינוי מפתח מנתק את התרגום הקיים ממחרוזת המקור.
2. השתמשו במצייני מיקום ממוספרים, ולא בשרשור מחרוזות בקוד
כתבו את המשפט המלא בקובץ ה־.properties שלכם והשתמשו במצייני מיקום ממוספרים עבור תוכן משתנה במקום לשרשר מחרוזות בקוד.
// Incorrect (in code)
"Hello, " + username + "! You have " + count + " new messages."
# Correct (in .properties)
dashboard.greeting = Hello, {0}! You have {1} new messages.
שפות רבות משנות את סדר המילים ואת כללי ההתאמה התחבירית, ולכן פיצול משפטים למקטעים הופך תרגום נכון לבלתי אפשרי.
3. תמכו בצורות רבים באמצעות ChoiceFormat, ICU, או מפתחות סיומת
עבור צורות רבים ב־Java סטנדרטית, ChoiceFormat עובד ישירות בתוך .properties:
messages.count = {0,choice,0#no messages|1#one message|1<{0} messages}
Java מעבדת זאת בזמן ריצה ומחזירה את הצורה הנכונה על סמך הערך שהועבר. ChoiceFormat הוא פשוט אך מוגבל להתאמת טווחי מספרים. הוא אינו תומך באופן מובנה בכללי צורות רבים מורכבים.
עבור צורות רבים תלויות־שפה (one/few/many/other של פולנית, שש הצורות של ערבית), השתמשו ב־MessageFormat של ICU4J:
String pattern = "{0, plural, one {# note} other {# notes}}";
String result = new com.ibm.icu.text.MessageFormat(pattern, locale).format(new Object[]{count});
או קודדו צורות רבים כמפתחות נפרדים עם סיומות מקובלות כדי ש־PTC תוכל ליצור את קטגוריות הרבים הנכונות לכל שפה:
notes.count.zero=No notes yet
notes.count.one={0} note
notes.count.other={0} notes
PTC יוצרת את קטגוריות הרבים הנכונות לכל שפת יעד. פולנית מקבלת one / few / many / other. יפנית מקבלת רק other.
4. בצעו Escape ל־=, :, # ו־\ באמצעות לוכסן שמאלי
לתווים כמו =, :, # ו־\ יש משמעות מיוחדת בקובצי .properties:
=או:מפרידים בין מפתחות לערכים.#או!מתחילים הערה.\מציג רצפי Escape (כמו\nלשורה חדשה).
בצעו Escape באמצעות לוכסן אחורי היכן שנדרש:
support.link = Visit us at https\://support.example.com
5. שמרו את קובצי ה־.properties בקידוד UTF-8
שמרו תמיד קובצי .properties בקידוד UTF-8. בלעדיו, תווים שאינם ASCII ישתבשו והתרגומים יהפכו לבלתי קריאים. בעבר קובצי .properties של Java היו בקידוד ISO-8859-1, מה שדרש שימוש ב־Escape של \uXXXX עבור תווים שאינם ASCII. מגרסה 9 ומעלה, Java קוראת אותם כ־UTF-8 כברירת מחדל, לכן בדקו את גרסת זמן הריצה שלכם לפני שתסתמכו על UTF-8 גולמי.
6. הרחיקו מהקוד את כל הטקסט שמוצג למשתמשים
אם מחרוזת גלויה למשתמשים, מקומה בקובץ .properties. מחרוזות מוטמעות בקוד לא יתורגמו. האפליקציה שלכם תציג בסופו של דבר תערובת של שפות.
עצבו תאריכים, זמנים, מספרים ומטבעות באמצעות פונקציות עזר מותאמות־locale
לא כל מה שדורש לוקליזציה נמצא בקובץ .properties. תאריכים, זמנים, מספרים וערכי מטבע מעוצבים בקוד בזמן ריצה, ועיצוב נכון שלהם חשוב לא פחות מהמחרוזות המתורגמות שלכם.
תאריכים עם DateTimeFormatter:
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.format.FormatStyle;
LocalDate today = LocalDate.now();
DateTimeFormatter formatter = DateTimeFormatter
.ofLocalizedDate(FormatStyle.LONG)
.withLocale(Locale.of("fr"));
System.out.println(today.format(formatter));
// -> "27 mai 2026"
מטבע עם NumberFormat:
import java.text.NumberFormat;
import java.util.Currency;
NumberFormat formatter = NumberFormat.getCurrencyInstance(Locale.of("de", "DE"));
formatter.setCurrency(Currency.getInstance("EUR"));
System.out.println(formatter.format(1999.99));
// -> "1.999,99 €"
השתמשו תמיד במעצבים (formatters) מותאמי־locale. לעולם אל תטמיעו בקוד "$", מפרידי אלפים כמו ",", או תבניות "MM/DD/YYYY".
חיבור ResourceBundle ל־Spring Boot בעזרת MessageSource
Spring Boot עוטף את ResourceBundle ב־bean מסוג MessageSource שמשתלב עם תכונות ה־i18n של ה־framework. הוא מכסה גם הודעות אימות, תבניות Thymeleaf, וזיהוי locale בבקשות רשת.
הגדירו בקובץ application.properties:
spring.messages.basename=messages
spring.messages.encoding=UTF-8
spring.messages.fallback-to-system-locale=false
מקמו את messages.properties, messages_es.properties, וכן הלאה תחת src/main/resources/.
שימוש ב־controller:
import org.springframework.context.MessageSource;
import org.springframework.context.i18n.LocaleContextHolder;
@RestController
public class GreetingController {
private final MessageSource messageSource;
public GreetingController(MessageSource messageSource) {
this.messageSource = messageSource;
}
@GetMapping("/greeting")
public String greeting(@RequestParam String name) {
return messageSource.getMessage(
"app.greeting",
new Object[]{name},
LocaleContextHolder.getLocale()
);
}
}
הגדירו את ה־locale resolver כך שיקרא מכותרת Accept-Language או מפרמטר ב־URL:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.LocaleResolver;
import org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver;
import org.springframework.web.servlet.i18n.LocaleChangeInterceptor;
@Configuration
public class I18nConfig implements WebMvcConfigurer {
@Bean
public LocaleResolver localeResolver() {
AcceptHeaderLocaleResolver resolver = new AcceptHeaderLocaleResolver();
resolver.setDefaultLocale(Locale.ENGLISH);
return resolver;
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
LocaleChangeInterceptor interceptor = new LocaleChangeInterceptor();
interceptor.setParamName("lang");
registry.addInterceptor(interceptor);
}
}
כעת GET /greeting?name=World&lang=es מחזיר את הגרסה הספרדית.
תרגום קובצי .properties של Java עם PTC ב־5 שלבים
- התחילו פרויקט ב־PTC ובחרו את ה־locale של המקור שלכם (אנגלית /
messages.properties). - העלו את קובצי ה־
.propertiesשלכם והגדירו נתיבי פלט. PTC מנתחת את מבנה המפתח-ערך, מזהה מצייני מיקום שלMessageFormat({0},{1}) ותבניותChoiceFormat, וקוראת כל הערת#כהקשר למתרגם. - הוסיפו תיאור קצר של אפליקציית ה־Java שלכם וקהל היעד. PTC משתמשת במידע זה כדי לתרגם בטון ובטרמינולוגיה הנכונים.
- בחרו שפות יעד ואשרו. תקופת הניסיון מכסה 20,000 מילים ל־2 שפות, ללא צורך בכרטיס אשראי.
- הורידו קובצי
.propertiesמתורגמים מלשונית Files. קובץ אחד לכל שפה, עם הסיומת המתאימה (messages_es.properties,messages_fr.properties). זהים מבנית למקור: אותם מפתחות, אותם מצייני מיקום, ערכים מתורגמים.
מקמו אותם ב־src/main/resources/, הריצו build מחדש, ו־ResourceBundle.getBundle("messages", locale) יזהה את השפות החדשות באופן אוטומטי. ההגדרה כולה אורכת כ־5 דקות.
אוטומציה של תרגום Java בכל שחרור גרסה עם Git או ה־API של PTC
תרגום חד־פעמי הוא משימה פשוטה. שמירה על תרגומים עדכניים ככל שהאפליקציה שלכם מתפתחת היא משימה קשה יותר. כל מחרוזת חדשה, כל עדכון תוכן, וכל מפתח שהוסר צריכים לעבור לכל שפה. PTC מציעה שתי דרכים לאוטומציה של התהליך.
אינטגרציית Git. חברו את מאגר ה־GitHub, ה־GitLab, או ה־Bitbucket שלכם ל־PTC. מערכת PTC מנטרת את קובץ ה־.properties של המקור שלכם לאיתור שינויים. כאשר מחרוזת מתווספת או מתעדכנת, PTC מתרגמת אותה ומחזירה את הקבצים המעודכנים באמצעות merge request.
אינטגרציית CI/CD. אם אתם מעדיפים להשאיר הכול בתוך תהליך ה־build הקיים שלכם, ה־API של PTC מאפשר לכם להעלות את קובץ המקור שלכם ולאחזר תרגומים כחלק ממשימת ה־CI שלכם.
בצעו commit לקובץ .ptc-config.yml המציין את קובץ המקור שלכם ואת המיקום שאליו שייכים התרגומים:
# .ptc-config.yml
source_locale: en
files:
- file: src/main/resources/messages.properties
output: src/main/resources/messages_{{lang}}.properties
לאחר מכן, הוסיפו את פעולת PTC Translate ל־workflow שלכם. היא מכילה בתוכה גרסה מקובעת של ה־CLI של PTC, כך שה־build שלכם לא מוריד דבר בזמן ריצה:
# .github/workflows/translate.yml
name: Translate
on:
push:
branches: [main]
paths:
- 'src/main/resources/messages.properties'
workflow_dispatch: {}
jobs:
translate:
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
steps:
- uses: actions/checkout@v4
- uses: OnTheGoSystems/ptc-action@v1
with:
api-token: ${{ secrets.PTC_API_TOKEN }}
create-pr: true
PTC מסנכרנת את מחרוזות המקור החדשות, מתרגמת רק את מה שהשתנה, ופותחת PR עם קובצי ה־messages_es.properties וה־messages_fr.properties המעודכנים, וכן הלאה. עבור פרויקטים של Maven ו־Gradle, אותו תהליך עובד בדיוק. ל־PTC לא משנה באיזה כלי build אתם משתמשים. שתי הגישות מבטיחות שהוספת שפה חדשה בעתיד תהיה שינוי הגדרה, ולא תהליך ידני חדש.
סקירה חזותית של התרגום לאפליקציית ה־Java שלכם - לשחרר ללא QA ידני לכל שפה
קובץ .properties מתורגם הוא הכרחי אך לא מספיק. בין אם אפליקציית ה־Java שלכם היא שירות רשת של Spring Boot שמגיש HTML, אפליקציית שולחן עבודה של Swing, או כלי CLI בצד השרת, התוצאה המרונדרת עשויה להכיל בעיות שאף סקירה ברמת המחרוזת לא תוכל לתפוס:
- תווית בגרמנית שחורגת מהכפתור (הצפה) ב־Swing.
- הודעת אימות בצרפתית עם צורה דקדוקית שגויה.
- מחרוזת מוטמעת בקוד באנגלית מחוץ ל־
messageSource.getMessage()שמוצגת ללא תרגום.
ה־AI Visual QA של PTC מכסה את שתי הווריאציות של אפליקציות Java:
- עבור Spring Boot או כל אפליקציית Java מבוססת רשת: התקינו את תוסף הדפדפן של PTC והקליטו מעבר מוקלט על העמודים הקריטיים של האפליקציה שלכם. PTC מריצה אותו מחדש בכל שפת יעד לאחר כל עדכון תרגום.
- עבור שולחן עבודה (Swing, JavaFX), שרת (CLI), או כל אפליקציית Java שאינה מבוססת דפדפן: העלו צילומי מסך של אפליקציית ה־Java הפועלת בכל שפת יעד. ה־vision AI של PTC סוקר כל מסך.
בעיות ש־PTC יכולה לתקן בקובצי ה־.properties (פועל/שם עצם, הצפת פריסה, משמעות שגויה) מתוקנות באופן אוטומטי. בעיות בקוד ה־Java שלכם (קריאת messageSource.getMessage() חסרה, מחרוזת מוטמעת בקוד, שרשור משפטים שאמור להשתמש ב־MessageFormat) חוזרות כפרומפטים מוכנים להדבקה עבור Cursor או Claude Code.
התוצאה: JAR רב-לשוני ומאומת בכל שחרור גרסה. לא רק קובצי property מתורגמים.
תרגום הערות גרסה, קובצי README, ואימיילים ללקוחות
הערות הגרסה שלכם, קובצי ה־README במאגר ה־Maven הפנימי שלכם או ב־GitHub, אימיילים המיועדים ללקוחות, תיעוד התמיכה, ועמודי ה־wiki הפנימיים שלכם חיים מחוץ ל־.properties. ה־Paste to Translate של PTC מטפל בתוכן הזה באותו פרויקט. הדביקו את טקסט המקור בלוח הבקרה של PTC, בחרו שפות יעד, וקבלו בחזרה תרגומים שמשתמשים באותו מילון מונחים ובאותו טון המותג כמו המחרוזות בתוך האפליקציה שלכם.
תרגום נתוני אנטרפרייז, קריאות תמיכה, ותוכן הלקוח באמצעות ה־API של PTC
נתוני אנטרפרייז, קריאות תמיכה, ערכים במאגר המידע, ותוכן שנשלח על ידי לקוחות דורשים תרגום עם הגעתם. ה־REST API של PTC מתרגם את התוכן הזה לפי דרישה עם אימות טוקן Bearer, תוך שימוש באותו מילון מונחים ובאותו טון המותג כמו תרגומי ה־.properties שלכם.
PTC מתרגמת את אפליקציית ה־Java שלכם וגם סוקרת את התוצאה הפועלת
התחילו את תקופת הניסיון שלכם של 30 יום - 20,000 מילים ל־2 שפות, ללא צורך בכרטיס אשראי. העלו את קובצי ה־.properties שלכם, קבלו גרסאות מתורגמות תוך דקות, ואז העלו צילומי מסך (או התקינו את תוסף הדפדפן עבור Spring Boot) ותנו ל־PTC לאמת את האפליקציה הפועלת.
ראו גם:
- תרגום אפליקציות Java עם בינה מלאכותית - סקירת השירות לצוותי Java.
- מדריך ה־API של PTC - נקודות קצה של REST עבור אינטגרציית CI.
- לוקליזציית תוכנה מבוססת בינה מלאכותית שנבנתה עבור צינורות CI/CD - סקירת השירות לצוותי פיתוח.