Java and Lokalise integration for internationalization (i18n)

Java internationalization (i18n): translate your Java app/website

Internationalization has become an invaluable method for engaging users and providing a seamless experience in today’s globalized world. By tailoring your Java app to support multiple languages and cultural nuances, you make it accessible to users across different regions, ensuring they feel right at home. In this article, we’ll explore how Java internationalization can help you translate your apps or websites effectively and build software that supports diverse audiences with ease.

    Special thanks to Anton Malich for insights and reviewing the source code.

    Internationalization in Java

    So, you have an exciting idea for a Java app or website, or maybe you’re managing a well-established Java application at work. But what happens when your application needs to support multiple languages? It must operate seamlessly, not only in English but also in a variety of other languages to cater to a global audience.

    That’s where Java internationalization comes in.

    Support for Java internationalization

    When it comes to software localization and supporting different languages in Java, three main concepts are essential to understand. These elements enable you to adapt your applications for different regions and languages effectively:

    1. Locale class: Objects representing the specific geographical, political, and cultural regions you plan to support.
    2. Resources: Locale-specific data stored in the form of classes or properties files.
    3. ResourceBundle class: Objects used to fetch data for the relevant locales from the appropriate resources.

    These classes are built into the java.util package, simplifying the implementation of Java internationalization in your web application or software.

    Rules to follow

    When adding language resources, ensure you follow these rules:

    • Resource file location: All resource files must reside in the same package.
    • Naming convention: All resource files must share a common base name. This base name is crucial and will be referenced throughout your code. You can choose any name you prefer.

    For example:

    • The default resource should use only the base name:
      • bundle.properties or Bundle.java
    • Additional properties files must follow this pattern:
      • base name _ language suffix
        • Example: bundle_fr.properties or Bundle_fr.java

    Narrowing down locales

    If you need to target a specific country within a language, you can add more resource files using a country suffix. For instance:

    • base name _ language suffix _ country suffix
      • Example: bundle_en_US.properties or Bundle_en_US.java

    For even more granularity, you can include a variant suffix:

    • base name _ language suffix _ country suffix _ variant suffix
      • Example: bundle_th_TH_TH.properties or Bundle_th_TH_TH.java

    By following these conventions, you ensure your Java application adheres to internationalization best practices, making it easy to scale for new locales.

    Simple translations in Java

    To understand how internationalization works in Java, let’s build a basic localization example using the features we discussed earlier.

    Create a new Java application

    Start by creating a new Java application named java-i18n. This will serve as the foundation for demonstrating how to implement simple translations in Java.

    Create a resource bundle

    The first step in Java internationalization is to add language resources. These resources will serve as the foundation for localizing your application into multiple languages.

    Resources in property file form

    The simplest way to store localization data is by using Java properties files. These files are handled by the PropertyResourceBundle class and are perfect for Java localization.

    1. Create the resource package:
      Add a new res package within your main package. Inside it, create a bundle.properties file.
    2. Define key-value pairs:
      In the properties file, include the words or phrases to be internationalized in a key-value format:
    hello=Hello
    welcome=Welcome to my app
    ok=OK
    cancel=Cancel
    tryagain=Please try again
    1. Here, bundle is the base name for the resource file.
    2. The bundle.properties file acts as the default resource file, used when no locale-specific file matches.

    Advantages:

    • Updating resource files doesn’t require recompilation, which streamlines maintenance.

    Limitations:

    • Resource values are restricted to strings.

    Resources in Java class form

    Alternatively, you can create resources by extending the ListResourceBundle abstract class. This approach allows you to use more complex objects as resource values.

    In the res package, create a Bundle class extending the ListResourceBundle class. Override the getContents method:

    package res;
    
    import java.util.ListResourceBundle;
    
    public class Bundle extends ListResourceBundle {
        @Override
        protected Object[][] getContents() {
            return new Object[][] {
                    {"hello", "Hello"},
                    {"ourfeatures", new String[] {
                        "Collaborative Translation", 
                        "Localization Workflow Management", 
                        "Localization Process Automation"
                    }}
            };
        }
    }

    Benefits:

    • Supports any type of object as a resource value.
    • Reduces overhead and improves garbage collection compared to serialized property files.

    Add more resources

    To localize your app for Italian-speaking users, add another properties file with the same keys but with Italian translations as values.

    Create a new properties file. Add a bundle_it_IT.properties file in the same package with the following content:

    hello=Ciao
    welcome=Benvenuti nella mia app
    ok=OK
    cancel=Annulla
    tryagain=Per favore riprova

    Alternatively, create a resource class. You can also use a Bundle_it_IT class:

    package res;
    
    import java.util.ListResourceBundle;
    
    public class Bundle_it_IT extends ListResourceBundle {
        @Override
        protected Object[][] getContents() {
            return new Object[][] {
                    {"hello", "Ciao"},
                    {"ourfeatures", new String[] {"Traduzione Collaborativa", "Gestione del flusso di lavoro di localizzazione", "Automazione del processo di localizzazione"}}
            };
        }
    }

    These resources collectively form a resource bundle, which is essential for Java translation and i18n.

    Add some locale class objects

    To represent specific geographical, political, or cultural regions, you need to create Locale objects. For instance, in the main method of your java-i18n project, you can define a Locale for Italian speakers in Italy:

    Locale locale_it_IT = new Locale("it", "IT");

    If you encounter deprecation warnings, use the updated approach:

    Locale locale_it_IT = Locale.of("it", "IT");

    For a complete list of locales supported in Java 8, refer to the official documentation.

    Use ResourceBundle class

    Now that we have created our resource bundle, let’s fetch language-specific data from it using the ResourceBundle class. To do this, call the ResourceBundle.getBundle static method, providing the fully-qualified class name of the base name as the first parameter.

    For example, to retrieve data for the Italian (it-IT) locale:

    ResourceBundle resourceBundle = ResourceBundle.getBundle("res.bundle", locale_it_IT);
    
    System.out.println(resourceBundle.getString("welcome"));

    This will correctly localize and print the specific value corresponding to the it-IT country code defined in your resource bundle.

    Handling missing locales

    But what happens if you request data for a locale not present in your resource bundle? For example:

    Locale locale_ru_RU = new Locale("ru", "RU");
    
    ResourceBundle resourceBundle = ResourceBundle.getBundle("res.bundle", locale_ru_RU);
    
    System.out.println(resourceBundle.getString("welcome"));

    In this case, the program will fall back to the default resource file (bundle.properties) and print the value from the en-US locale, as it is the default resource. This behavior is consistent with Java’s internationalization mechanism, ensuring your application always provides a response, even when the exact locale is unavailable.

    Switching between locales

    Let’s create a simple GUI application to visualize how locale switching works in a Java internationalization (i18n) application. Using Java Swing, we’ll design a GUI that utilizes the language resources we created earlier. The application will include a “Switch” button to toggle the app’s language each time it’s pressed.

    Prerequisites

    Before proceeding, ensure you have the following tools:

    • NetBeans IDE: I will be using NetBeans IDE 11.3 for Java GUI software development.
    • Maven: For managing project dependencies.

    Set up the project

    1. Create a new Maven project:
      Name the project java-i18n-gui.
    2. Set up the GUI package:
      Add a gui package to the project.
    3. Create a Swing form:
      Inside the gui package, create a new JFrame form named SwitchLang.

    Add GUI components

    To build the user interface for our locale-switching application, we’ll add the following components to the SwitchLang form:

    1. JLabel components:
      • jLabelHello: Displays a localized greeting.
      • jLabelWelcome: Displays a localized welcome message.
    2. JButton components:
      • jButtonOk: Represents an “OK” button with localized text.
      • jButtonCancel: Represents a “Cancel” button with localized text.
      • jButtonSwitchLang: A button labeled “Switch” that toggles the app’s language when pressed.

    Add language resources

    To synchronize the SwitchLang JFrame form with localized resources, follow these steps:

    1. Set up the resources folder:
      • Using Maven conventions, click the Files tab in NetBeans.
      • Create a resources folder inside the src/main/ directory of your project.
      • Maven will automatically mark src/main/resources as a resource directory during the next build.
    2. Create the default resource file:
      • Inside the resources folder, create a bundle.properties file.
      • This file will act as the default resource file for your resource bundle.
    3. Link the resource file to the form:
      • Open the SwitchLang form from the Projects window and switch to the Design tab.
      • In the Navigator section (lower-left corner), click the root node labeled “Form SwitchLang.”
      • In the Properties window (on the right), locate the Properties Bundle field.
        • Browse to src/main/resources and select the bundle.properties file.
      • Check the Automatic Internationalization option in the same window.
    4. Define default resource values:
      Open the bundle.properties file and replace its content with the following:
    SwitchLang.jLabelHello.text=Hello
    SwitchLang.jLabelWelcome.text=Welcome to my app
    SwitchLang.jButtonOk.text=OK
    SwitchLang.jButtonCancel.text=Cancel
    SwitchLang.jButtonSwitchLang.text=Switch

    These keys correspond to the Swing elements created earlier and define their default (en-US) text.

    Add an Italian locale file:

    • Create a new file named bundle_it_IT.properties in the resources folder.
    • Add the following content:
    SwitchLang.jLabelHello.text=Ciao
    SwitchLang.jLabelWelcome.text=Benvenuti nella mia app
    SwitchLang.jButtonOk.text=OK
    SwitchLang.jButtonCancel.text=Annulla
    SwitchLang.jButtonSwitchLang.text=Interruttore

    This file defines text for the it-IT locale.

    Now, the resource bundle is synchronized with the SwitchLang JFrame form elements, and the application is ready for locale-specific text display.

    Code the switch button functionality

    Now, let’s implement the functionality for the jButtonSwitchLang button to allow the user to switch the application’s locale to Italian.

    Create the action method:

    • Double-click the jButtonSwitchLang button in the Editor.
    • This will create a jButtonSwitchLangActionPerformed method where you can define the behavior triggered by the button.

    Retrieve the Italian locale resource bundle:
    Inside the jButtonSwitchLangActionPerformed method, add the following code to retrieve the resource bundle for the it-IT locale:

    Locale locale_it_IT = new Locale("it", "IT");
    ResourceBundle resourceBundleIT = ResourceBundle.getBundle("bundle", locale_it_IT);

    Ensure the necessary classes (Locale and ResourceBundle) from the java.util package are imported.

    Update Swing element text:
    Use the resource bundle to update the text of your Swing components:

    jLabelHello.setText(resourceBundleIT.getString("SwitchLang.jLabelHello.text"));
    jLabelWelcome.setText(resourceBundleIT.getString("SwitchLang.jLabelWelcome.text"));
    jButtonOk.setText(resourceBundleIT.getString("SwitchLang.jButtonOk.text"));
    jButtonCancel.setText(resourceBundleIT.getString("SwitchLang.jButtonCancel.text"));
    jButtonSwitchLang.setText(resourceBundleIT.getString("SwitchLang.jButtonSwitchLang.text"));

    Test the application:

    • Run the java-i18n-gui application.
    • Click the Switch button to verify that the locale changes and the UI updates to display the Italian text.

    A few other Java internationalization features

    In addition to resource bundles and locales, Java offers additional features to help with localization tasks. Let’s explore a couple of these features.

    Pluralization

    Proper pluralization is often necessary when dealing with internationalized text. For example, consider representing the number of apples in English:

    • 0 apples
    • 1 apple
    • 2 apples

    A simple method to handle this in Java might look like this:

    public static String getAppleCountMsg(int count) {
        if (count == 1) {
            return "1 apple";
        } else if (count == 0 || count > 1) {
            return count + " apples";
        } else {
            return "You don't count apples in minus numbers! Please input a whole number";
        }
    }

    While functional, this approach can quickly become tedious and error-prone, especially when dealing with multiple languages.

    Using ChoiceFormat for pluralization

    Java’s ChoiceFormat class simplifies pluralization by reducing the clutter and making the code more maintainable. Here’s how it can be used:

    public static ChoiceFormat getAppleCountMsgChoiceFormat() {
        double[] minAppleCount = {0, 1, 2};
        String[] appleCountFormat = {"apples", "apple", "apples"};  
        return new ChoiceFormat(minAppleCount, appleCountFormat);
    }

    Here’s a breakdown of the parameters passed to ChoiceFormat:

    1. Intervals (double array):
      • {0, 1, 2} defines the starting points of intervals.
      • Interval [0, 1) corresponds to "apples".
      • Interval [1, 2) corresponds to "apple".
      • Interval [2, ∞) corresponds to "apples".
    2. Strings (String array):
      • {"apples", "apple", "apples"} defines the text for each interval.

    Retrieving pluralized messages

    Once you have a ChoiceFormat object, you can use it to format messages based on the provided count:

    public static String getAppleCountMsg(ChoiceFormat appleCountChoiceFormat, int count) {
        return count + " " + appleCountChoiceFormat.format(count); 
    }

    Example usage:

    ChoiceFormat appleCountChoiceFormat = getAppleCountMsgChoiceFormat();
    System.out.println(getAppleCountMsg(appleCountChoiceFormat, 0)); // Output: "0 apples"
    System.out.println(getAppleCountMsg(appleCountChoiceFormat, 1)); // Output: "1 apple"
    System.out.println(getAppleCountMsg(appleCountChoiceFormat, 5)); // Output: "5 apples"

    Considerations for other languages

    It’s important to note that pluralization rules vary between languages. For example:

    • English has two plural forms: singular and plural.
    • Other languages, like Arabic or Russian, may have more complex pluralization rules.

    You will need to manually create separate ChoiceFormat objects for each language supported in your internationalized application to account for these differences.

    Using ICU MessageFormat for advanced pluralization

    While the ChoiceFormat class in Java helps manage basic pluralization, it can become cumbersome when dealing with complex plural rules in languages with multiple plural forms (e.g., Arabic, Russian). For such cases, the ICU MessageFormat library provides a robust solution, supporting language-specific pluralization rules defined by the Unicode CLDR (Common Locale Data Repository).

    Setting up ICU4J

    To use ICU MessageFormat in your Java application, include the ICU4J library in your project. For Maven, add the following dependency:

    <dependency>
        <groupId>com.ibm.icu</groupId>
        <artifactId>icu4j</artifactId>
        <version>72.1</version>
    </dependency>

    For Gradle:

    implementation("com.ibm.icu:icu4j:72.1")

    Using ICU MessageFormat for pluralization

    The ICU MessageFormat class allows you to define plural rules dynamically based on the locale. Here’s an example of using it to handle pluralization for a message about apples:

    import com.ibm.icu.text.MessageFormat;
    import java.util.Locale;
    
    public class ICUPuralizationExample {
        public static void main(String[] args) {
            // Define the pluralization pattern
            String pattern = "{0, plural, one {# apple} other {# apples}}";
    
            // Create a MessageFormat instance for a specific locale
            MessageFormat messageFormat = new MessageFormat(pattern, Locale.ENGLISH);
    
            // Format pluralized messages
            System.out.println(messageFormat.format(new Object[]{1})); // Output: "1 apple"
            System.out.println(messageFormat.format(new Object[]{5})); // Output: "5 apples"
        }
    }

    Adding language-specific pluralization

    ICU MessageFormat handles locale-specific rules automatically. For example, Russian uses distinct forms for 1, 2-4, and 5 or more. The same MessageFormat can be adapted to handle Russian pluralization:

    public class ICULocaleExample {
        public static void main(String[] args) {
            // Define the pluralization pattern
            String pattern = "{0, plural, one {# яблоко} few {# яблока} other {# яблок}}";
    
            // Create a MessageFormat instance for the Russian locale
            MessageFormat messageFormat = new MessageFormat(pattern, new Locale("ru", "RU"));
    
            // Format pluralized messages
            System.out.println(messageFormat.format(new Object[]{1})); // Output: "1 яблоко"
            System.out.println(messageFormat.format(new Object[]{3})); // Output: "3 яблока"
            System.out.println(messageFormat.format(new Object[]{5})); // Output: "5 яблок"
        }
    }

    In this example:

    • The one rule applies to singular numbers like 1.
    • The few rule applies to numbers ending in 2, 3, or 4 (excluding 12-14).
    • The other rule applies to numbers like 0, 5, or anything not covered by the first two rules.

    Why ICU is better for pluralization

    1. Locale-awareness: Automatically adapts to the plural rules of the provided locale.
    2. Ease of use: Allows complex pluralization rules to be defined in a single, readable pattern.
    3. Flexibility: Supports not just pluralization but also gender and select rules for advanced localization.

    Date and time

    Handling localized date and time formats is a critical part of Java internationalization, especially in applications that cater to users from multiple regions. Java provides the DateFormat class to simplify this task.

    Using getDateTimeInstance

    The getDateTimeInstance method in the DateFormat class allows you to retrieve locale-specific date and time formats. For example, here’s how you can get the current date and time in the SHORT format for a given locale:

    public String getCurrentDateAndTime(Locale locale) {
        DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.SHORT,
                                                               DateFormat.SHORT, 
                                                               locale);
        return dateFormat.format(new Date());
    }

    Example usage:

    Locale locale_us = new Locale("en", "US");
    Locale locale_fr = new Locale("fr", "FR");
    
    System.out.println(getCurrentDateAndTime(locale_us)); // Output: 12/23/24, 4:30 PM
    System.out.println(getCurrentDateAndTime(locale_fr)); // Output: 23/12/24, 16:30

    This ensures that the date and time are formatted appropriately for different regions.

    Using DateTimeFormatter

    Introduced in Java 8, the DateTimeFormatter class in the java.time package offers greater flexibility and modern formatting options. It works seamlessly with Locale to create locale-specific date and time formats.

    public String getLocalizedDateAndTime(Locale locale) {
        DateTimeFormatter formatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.SHORT)
                                                        .withLocale(locale);
        return LocalDateTime.now().format(formatter);
    }

    Example usage:

    Locale locale_de = new Locale("de", "DE");
    Locale locale_jp = new Locale("ja", "JP");
    
    System.out.println(getLocalizedDateAndTime(locale_de)); // Output: 23.12.24, 16:30
    System.out.println(getLocalizedDateAndTime(locale_jp)); // Output: 2024/12/23 16:30

    Formatting numbers and currency

    In addition to dates and times, Java internationalization also includes number and currency formatting. The NumberFormat class can be used to format values based on a given locale.

    Example:

    public String getFormattedCurrency(Locale locale, double amount) {
        NumberFormat currencyFormat = NumberFormat.getCurrencyInstance(locale);
        return currencyFormat.format(amount);
    }

    Example usage:

    Locale locale_uk = new Locale("en", "GB");
    Locale locale_in = new Locale("hi", "IN");
    
    System.out.println(getFormattedCurrency(locale_uk, 1234.56)); // Output: £1,234.56
    System.out.println(getFormattedCurrency(locale_in, 1234.56)); // Output: ₹1,234.56

    By leveraging these features, Java makes it easy to handle date, time, and number formatting in internationalized applications. These tools are invaluable when localizing web applications, handling HTTP requests, or developing software for a global audience.

    Errors and fallbacks in Java internationalization

    Errors can arise in internationalized applications when translations are missing, locales are unsupported, or external services (like Google Cloud Translation API) fail to respond. To ensure your Java application remains robust, it’s essential to implement fallback mechanisms.

    Handling missing resources

    When using ResourceBundle, a missing resource or locale may cause an exception or lead to undefined behavior. To handle this gracefully, Java automatically falls back to the default resource bundle (e.g., bundle.properties). However, you can add custom fallback logic to ensure meaningful behavior.

    Example: Adding a fallback message for missing translations:

    import java.util.Locale;
    import java.util.MissingResourceException;
    import java.util.ResourceBundle;
    
    public class TranslationFallbackExample {
        public static void main(String[] args) {
            Locale locale_ru = new Locale("ru", "RU"); // A locale without translations
            String key = "welcome";
    
            ResourceBundle resourceBundle;
            try {
                resourceBundle = ResourceBundle.getBundle("bundle", locale_ru);
                System.out.println(resourceBundle.getString(key));
            } catch (MissingResourceException e) {
                // Fallback to default message
                System.out.println("Translation not found. Default message: Welcome!");
            }
        }
    }

    This ensures the application gracefully handles scenarios where a specific locale’s resource bundle is missing or incomplete.

    Dealing with API errors

    When working with external APIs like the Google Cloud Translation API, network issues or service outages can disrupt functionality. Implement retry logic or fallbacks to a default translation mechanism to maintain a seamless user experience.

    Example: Fallback logic with API failure:

    import com.google.cloud.translate.Translate;
    import com.google.cloud.translate.TranslateOptions;
    import com.google.cloud.translate.Translation;
    
    public class ApiFallbackExample {
        public static void main(String[] args) {
            String textToTranslate = "Hello, world!";
            String translatedText;
    
            try {
                Translate translate = TranslateOptions.getDefaultInstance().getService();
                Translation translation = translate.translate(
                        textToTranslate,
                        Translate.TranslateOption.targetLanguage("es")
                );
                translatedText = translation.getTranslatedText();
            } catch (Exception e) {
                // Log the error and use a default translation
                System.err.println("Translation API failed: " + e.getMessage());
                translatedText = "Hola, mundo!"; // Fallback to a predefined translation
            }
    
            System.out.println(translatedText);
        }
    }

    Best practices for error handling and fallbacks

    1. Use meaningful defaults:
      Always provide a sensible default message in case translations are unavailable. This ensures users can still understand the UI.
    2. Log errors:
      Keep track of missing translations or failed API calls using a logging framework (e.g., SLF4J or Log4j). This helps identify gaps in localization.
    3. Cache translations:
      Cache translated content to minimize reliance on external APIs during network issues or outages.
    4. Validate resource bundles:
      Regularly test your ResourceBundle files to ensure all required keys exist for every locale.
    5. Notify users gracefully:
      If a fallback is used, consider notifying users with a subtle message or log for development purposes.

    Use Lokalise for Java internationalization

    As demonstrated in our Java translation and internationalization examples, properly internationalizing your Java app can be a time-consuming and complex task. Managing resource bundles, handling pluralization, and formatting localized data often require significant effort. Why not simplify this process with a professional translation management system like Lokalise?

    Why Lokalise?

    Lokalise offers a comprehensive platform for managing translation files and streamlining the localization workflow. It provides several features to make internationalization more efficient:

    • Google translations: Generate initial translations with ease.
    • Collaborative translations: Enable teams to work together in real time.
    • Quality Assurance tools: Ensure your translations meet high standards.
    • Integration support: Seamlessly integrate with various services and platforms.
    • Centralized management: Handle all translations through an intuitive dashboard.

    With Lokalise, you can save time and reduce the complexity of managing Java internationalization in your web applications or software projects.

    Getting started with Lokalise

    Follow these simple steps to start using Lokalise:

    1. Sign up for a free trial:
      Create a free account on Lokalise (no credit card required).
    2. Log in:
      Access your Lokalise dashboard.
    3. Create a project:
      Start a new project and name it however you like.
    4. Upload your translation files:
      Import your existing translation files (e.g., bundle.properties or other formats). Edit them as needed directly in Lokalise.
    5. Manage and deploy:
      Use Lokalise’s tools to refine your translations and export updated files to your Java application.

    More resources

    • Getting Started Guide: Explore step-by-step tutorials to help you kick off your Lokalise journey.
    • Lokalise API Documentation: Access a comprehensive list of REST commands to integrate and automate translation management in your projects.

    By leveraging Lokalise, you can simplify your workflow, ensure high-quality translations, and focus on building an exceptional Java application for a global audience.

    Meet Cloud Translation API

    As a bonus, let’s explore how to integrate Google Translate functionality into your Java application using the Google Cloud Translation API. This API, provided by Google Cloud Platform, allows you to perform basic text translations with ease.

    Before you begin, ensure that Maven is installed on your computer as it will be required for dependency management.

    Create Google Cloud project

    If you already have an existing Google Cloud project, you can skip this step and use it for your translation purposes. Otherwise, refer to the Google Cloud documentation for step-by-step instructions on creating a new project.

    Enable Google Cloud Translation API

    To get started, enable the Cloud Translation API for your project:

    1. Navigate to the Translation API homepage.
    2. Select your Google Cloud project from the dropdown menu.
    3. Click Enable to activate the API.

    Set up credentials

    To establish secure communication between the Cloud Translation API and your application, you need to set up credentials. Detailed instructions are available in the Authentication section of the Google Cloud documentation. Follow the steps to generate a service account key and download the JSON credentials file.

    Simple app with Cloud Translation API

    Let’s create a basic Java application, called the Translator application, to demonstrate how to perform translations using the Cloud Translation API Java client library.

    Create a Maven project

    Start by generating a new Maven project using the following command:

    mvn archetype:generate -DgroupId=com.lokalise -DartifactId=translate -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false

    This creates a project named translate under the com.lokalise group, following Maven conventions.

    Add dependencies to project

    Add the following dependency to your pom.xml file to include the Java client library for the Google Cloud Translation API:

    <dependency>
        <groupId>com.google.cloud</groupId>
        <artifactId>google-cloud-translate</artifactId>
        <version>2.28.0</version>
    </dependency>

    Note: The dependency version mentioned above might change over time. Check the Maven Central Repository to ensure you’re using the latest version.

    If you’re using Gradle, add this line to your build.gradle file:

    implementation(“com.google.cloud:google-cloud-translate:2.28.0”)

    Translator class

    Let’s implement the Translator class to perform text translation using the Google Cloud Translation API. This simple Java program demonstrates how to set up the translation service, translate text, and retrieve the translated result.

    import com.google.cloud.translate.Translate;
    import com.google.cloud.translate.TranslateOptions;
    import com.google.cloud.translate.Translation;
    
    public class Translator {
        public static void main(String[] args) {
            // Initialize Google Cloud Translation service
            Translate translate = TranslateOptions.getDefaultInstance().getService(); // 1
    
            // Text to translate
            String textToTranslate = "Localization in Java is fun";
    
            // Perform translation
            Translation translation = translate.translate(
                    textToTranslate,
                    Translate.TranslateOption.sourceLanguage("en"), // 2
                    Translate.TranslateOption.targetLanguage("it")
            );
    
            // Retrieve and print the translated text
            String translatedText = translation.getTranslatedText();
            System.out.println(translatedText);
        }
    }

    How it works

    1. Initializing the translation service:
      The TranslateOptions.getDefaultInstance().getService() method initializes the Google Cloud Translation API client. It uses credentials set via the GOOGLE_APPLICATION_CREDENTIALS environment variable. Ensure that this variable points to the JSON key file downloaded during the Set up credentials step.
    2. Specifying translation options:
      • The TranslateOption.sourceLanguage("en") parameter specifies the source language (English in this case).
      • The TranslateOption.targetLanguage("it") parameter specifies the target language (Italian).
      • The source language parameter is optional since the API can detect languages automatically. However, it is good practice to specify the source language explicitly to prevent misinterpretations.
    3. Performing translation:
      The translate.translate() method processes the input text and returns a Translation object containing the translated text.
    4. Retrieving the result:
      The getTranslatedText() method retrieves the translated string, which is then printed to the console.

    Output

    Running the program will print the Italian translation of the input text (textToTranslate) on the console. For example:

    La localizzazione in Java è divertente

    Supported languages

    The Google Cloud Translation API supports a wide range of languages. Refer to the list of supported languages to find the language codes you can use in the TranslateOption.targetLanguage() parameter.

    Conclusions on Java i18n

    In this tutorial, we explored the fundamentals of Java internationalization (i18n) and localization for your app or website. We walked through the process of setting up Google Cloud Translation API, integrating it into a simple Maven project, and performing basic text translations using its Java client library.

    We also delved into adding multi-language support to Java applications by leveraging Java’s built-in Locale and ResourceBundle classes. These tools, combined with our practical examples, showcased how to handle translations and build internationalized applications effectively.

    From implementing basic pluralization to exploring advanced options like ICU MessageFormat, you now have a strong foundation to create applications that cater to a global audience.

    That’s a wrap for this guide! We hope this article helps you kick-start your Java localization journey. Until next time—happy coding, and ciao, fellow developer!

    Further reading

    Related articles
    Stop wasting time with manual localization tasks. 

    Launch global products days from now.