PTC

מדריך בינאום Java: תרגום קובצי properties. באמצעות בינה מלאכותית

הגדירו ResourceBundle, ארגנו את קובצי ה־.properties, תרגמו ליותר מ־40 שפות באמצעות בינה מלאכותית, ואז תנו ל־PTC (Private Translation Cloud) לסקור את אפליקציית ה־Java הרצה באמצעות צילומי מסך או תוסף דפדפן. בסיום התהליך יהיה לכם קובץ JAR רב־לשוני מוכן להפצה, כשכל שפת יעד מאומתת לפני השחרור. לסקירה כללית של שירות ה־Java העצמאי, ראו תרגום אפליקציות Java באמצעות בינה מלאכותית.

ResourceBundle טוען את קובץ ה־properties. הנכון בזמן ריצה

מערכת ה־i18n של Java בנויה סביב שני דברים: קובצי .properties המאחסנים את המחרוזות המתורגמות שלכם, ומחלקת ResourceBundle שטוענת את הקובץ הנכון בזמן ריצה בהתבסס על ה־locale של המשתמש.

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

ResourceBundle bundle = ResourceBundle.getBundle("messages", Locale.FRENCH);
String greeting = bundle.getString("welcome.message");

זהו המנגנון כולו. שאר עבודת הלוקליזציה מתבצעת בקובצי ה־.properties עצמם, ולכן חשוב לבנות אותם נכון.

הגדרת ה־resource bundle עם messages_{locale}.properties

resource bundle הוא קבוצה של קובצי .properties החולקים שם בסיס (base name) משותף. שם הבסיס הוא חלק משם הקובץ שלפני סיומת ה־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)

אפליקציות גדולות משתמשות לעיתים קרובות במספר resource bundles כדי לשמור על הסדר:

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 לא ימצא את הקובץ בזמן ריצה.

טענו והשתמשו ב־bundle בקוד, עם 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:

  • = או : מפרידים בין מפתחות לערכים.
  • # או ! מתחילים הערה.
  • \ משמש לרצפי מילוט (כמו \n לשורה חדשה).

השתמשו בלוכסן אחורי (backslash) היכן שנדרש:

support.link = Visit us at https\://support.example.com

5. שמרו קובצי properties. בקידוד UTF-8

שמרו תמיד קובצי .properties בקידוד UTF-8. ללא קידוד זה, תווים שאינם ASCII ישתבשו והתרגומים יהפכו לבלתי קריאים. היסטורית, קובצי .properties ב־Java היו בקידוד ISO-8859-1, מה שדרש מילוט \uXXXX עבור תווים שאינם ASCII. החל מ־Java 9, המערכת קוראת אותם כ־UTF-8 כברירת מחדל, לכן בדקו את גרסת זמן הריצה שלכם לפני שתסתמכו על UTF-8 גולמי.

6. שמרו את כל הטקסט הפונה למשתמש מחוץ לקוד

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

פרמוט תאריכים, זמנים, מספרים ומטבעות באמצעות עוזרים מותאמי 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 EUR"

השתמשו תמיד במפרמטים (formatters) מותאמי locale. לעולם אל תטמיעו בקוד "$", פסיק כמפריד אלפים או תבניות כמו "MM/DD/YYYY".

חיבור ResourceBundle ל־Spring Boot באמצעות MessageSource

Spring Boot עוטף את ResourceBundle ב־bean מסוג MessageSource שמשתלב עם תכונות ה־i18n של הפריימוורק: הודעות אימות, תבניות 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 שלבים

  1. התחילו פרויקט PTC ובחרו את locale המקור שלכם (אנגלית / messages.properties).
  2. העלו את קובצי ה־.properties שלכם והגדירו נתיבי פלט. PTC מנתח את מבנה המפתח־ערך, מזהה מצייני מיקום של MessageFormat (כמו {0}, {1}) ותבניות ChoiceFormat, וקורא כל הערת # כהקשר למתרגם.
  3. הוסיפו תיאור קצר של אפליקציית ה־Java וקהל היעד שלכם. PTC משתמש בזה כדי לתרגם בטון ובטרמינולוגיה הנכונים.
  4. בחרו שפות יעד ואשרו. תקופת הניסיון בחינם מכסה 20,000 מילים ל־2 שפות, ללא כרטיס אשראי.
  5. הורידו קובצי properties. מתורגמים מלשונית קובצי משאבים. קובץ אחד לכל שפה, עם הסיומת הנכונה (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. המערכת תנטר שינויים בקובץ ה־.properties המקורי. כשמחרוזת מתווספת או מתעדכנת, PTC מתרגם אותה ומגיש את הקבצים המעודכנים בחזרה באמצעות pull request.

אינטגרציית CI/CD. אם אתם מעדיפים להשאיר הכל בתוך תהליך ה־build הקיים שלכם, ה־API של PTC מאפשר לכם להעלות את קובץ המקור ולקבל תרגומים כחלק מתהליך ה־CI:

# .github/workflows/translate.yml
name: PTC translate
on:
  push:
    branches: [main]
    paths:
      - 'src/main/resources/messages.properties'
jobs:
  translate:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Trigger PTC translation
        run: |
          curl -X POST https://api.ptc.wpml.org/v1/projects/${{ secrets.PTC_PROJECT_ID }}/sync \
            -H "Authorization: Bearer ${{ secrets.PTC_API_KEY }}"

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 מאומת ורב־לשוני בכל שחרור, ולא רק קובצי properties מתורגמים.

תרגום הערות גרסה, קובצי README ואימיילים ללקוחות

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

תרגום נתונים ארגוניים, כרטיסי תמיכה ותוכן לקוחות באמצעות ה־API של PTC

נתונים ארגוניים, כרטיסי תמיכה, פריטים במרכז הידע ותוכן המוגש על ידי לקוחות זקוקים לתרגום ברגע הגעתם. ה־REST API של PTC מתרגם תוכן זה לפי דרישה עם אימות Bearer-token, תוך שימוש באותו מילון מונחים וטון מותג כמו תרגומי ה־.properties שלכם.

תרגמו וסקרו את אפליקציית ה־Java שלכם

התחילו את תקופת הניסיון של 30 יום בחינם – 20,000 מילים ל־2 שפות, ללא כרטיס אשראי. העלו את קובצי ה־.properties שלכם, קבלו גרסאות מתורגמות תוך דקות, ואז העלו צילומי מסך (או התקינו את תוסף הדפדפן עבור Spring Boot) ותנו ל־PTC לאמת את האפליקציה הרצה.

נושאים קשורים: