Demo i18n mit branch

Internationalisierung mit Branch

Internationalisierung (i18n)

  • Internationalisierung ist der Prozess, eine Software so zu gestalten, dass sie in verschiedenen Sprachen und Regionen funktioniert.
  • Internationalisierung wird oft als i18n abgekürzt, da es 18 Buchstaben zwischen i und n gibt.
  • Internationalisierung beinhaltet die Übersetzung von Texten und die Anpassung von Formaten für verschiedene Sprachen und Regionen.

Demo Projekt

Das Demo-Projekt wird eine einfache Java-Applikation sein, die eine grafische Benutzeroberfläche (GUI) hat. Die Applikation wird einen Text und einen Button anzeigen. Der Text soll internationalisiert werden, um in verschiedenen Sprachen angezeigt zu werden, basierend auf der Nutzerauswahl.

Projektstruktur

src/main/java/
└── com
    └── example
        └── App.java

App.java

package com.example;

import javax.swing.*;

public class App {
    public static void main(String[] args) {
        JFrame frame = new JFrame("Demo App");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(400, 300);

        JMenuBar menuBar = new JMenuBar();
        JMenu fileMenu = new JMenu("File");
        JMenuItem exitItem = new JMenuItem("Exit");
        exitItem.addActionListener(e -> System.exit(0));
        fileMenu.add(exitItem);
        menuBar.add(fileMenu);
        frame.setJMenuBar(menuBar);

        JButton button = new JButton("Click Me");
        frame.getContentPane().add(button);

        frame.setVisible(true);
    }
}

Schritt 1: Branch erstellen

git checkout -b i18n

Schritt 2: Internationalisierung hinzufügen

src/main/resources/
 ├── messages.properties
 ├── messages_de_DE.properties
 └── messages_en_US.properties

messages_de_DE.properties

app.title=Demo-Anwendung
menu.file=Datei
menu.exit=Beenden
menu.settings=Einstellungen
button.clickMe=Klick Mich

messages_en_US.properties

app.title=Demo App
menu.file=File
menu.exit=Exit
menu.settings=Settings
button.clickMe=Click Me

App.java

package com.example;

import javax.swing.*;
import java.util.Locale;
import java.util.ResourceBundle;

public class App {
    private static JFrame frame;
    private static ResourceBundle messages = ResourceBundle
                    .getBundle("messages", Locale.forLanguageTag("en"));

    public static void main(String[] args) {
        frame = new JFrame(messages.getString("app.title"));
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(400, 300);

        JMenuBar menuBar = new JMenuBar();
        JMenu fileMenu = new JMenu(messages.getString("menu.file"));
        JMenuItem exitItem = new JMenuItem(messages.getString("menu.exit"));
        exitItem.addActionListener(e -> System.exit(0));
        fileMenu.add(exitItem);

        JMenu settingsMenu = new JMenu(messages.getString("menu.settings"));
        JMenuItem langEn = new JMenuItem("English");
        JMenuItem langDe = new JMenuItem("Deutsch");
        langEn.addActionListener(e -> switchLanguage("en-US"));
        langDe.addActionListener(e -> switchLanguage("de-DE"));
        settingsMenu.add(langEn);
        settingsMenu.add(langDe);

App.java

        menuBar.add(fileMenu);
        menuBar.add(settingsMenu);
        frame.setJMenuBar(menuBar);

        JButton button = new JButton(messages.getString("button.clickMe"));
        frame.getContentPane().add(button);

        frame.setVisible(true);
    }

    private static void switchLanguage(String langTag) {
        Locale locale = Locale.forLanguageTag(langTag);
        messages = ResourceBundle.getBundle("messages", locale);
        updateTexts();
    }

    private static void updateTexts() {
        frame.setTitle(messages.getString("app.title"));
        JMenuBar menuBar = frame.getJMenuBar();
        menuBar.getMenu(0).setText(messages.getString("menu.file"));
        menuBar.getMenu(0).getItem(0).setText(messages.getString("menu.exit"));
        menuBar.getMenu(1).setText(messages.getString("menu.settings"));
        JButton button = (JButton) frame.getContentPane().getComponent(0);
        button.setText(messages.getString("button.clickMe"));
    }
}

App.java

package com.example;

import javax.swing.*;
import java.util.Locale;
import java.util.ResourceBundle;

public class App {
    private static JFrame frame;
    private static ResourceBundle messages = ResourceBundle
                      .getBundle("messages", Locale.forLanguageTag("en"));

    public static void main(String[] args) {
        frame = new JFrame(messages.getString("app.title"));
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(400, 300);

        JMenuBar menuBar = new JMenuBar();
        JMenu fileMenu = new JMenu(messages.getString("menu.file"));
        JMenuItem exitItem = new JMenuItem(messages.getString("menu.exit"));
        exitItem.addActionListener(e -> System.exit(0));
        fileMenu.add(exitItem);

        JMenu settingsMenu = new JMenu(messages.getString("menu.settings"));
        JMenuItem langEn = new JMenuItem("English");
        JMenuItem langDe = new JMenuItem("Deutsch");
        langEn.addActionListener(e -> switchLanguage("en-US"));
        langDe.addActionListener(e -> switchLanguage("de-DE"));
        settingsMenu.add(langEn);
        settingsMenu.add(langDe);

        menuBar.add(fileMenu);
        menuBar.add(settingsMenu);
        frame.setJMenuBar(menuBar);

        JButton button = new JButton(messages.getString("button.clickMe"));
        frame.getContentPane().add(button);

        frame.setVisible(true);
    }

    private static void switchLanguage(String langTag) {
        Locale locale = Locale.forLanguageTag(langTag);
        messages = ResourceBundle.getBundle("messages", locale);
        updateTexts();
    }

    private static void updateTexts() {
        frame.setTitle(messages.getString("app.title"));
        JMenuBar menuBar = frame.getJMenuBar();
        menuBar.getMenu(0).setText(messages.getString("menu.file"));
        menuBar.getMenu(0).getItem(0).setText(messages.getString("menu.exit"));
        menuBar.getMenu(1).setText(messages.getString("menu.settings"));
        JButton button = (JButton) frame.getContentPane().getComponent(0);
        button.setText(messages.getString("button.clickMe"));
    }
}

Schritt 3: Testen

Die Funktionalität sollte nun getestet werden, um sicherzustellen, dass die Internationalisierung korrekt funktioniert.

Schritt 4: Änderungen überprüfen

git diff

Schritt 5: Änderungen zusammenführen

git checkout main
git merge i18n

Projektstruktur gesamt (maven)

MyProject/
│
├── src/
│   ├── main/
│   │   ├── java/
│   │   │   └── com/example/
│   │   │       └── App.java
│   │   ├── resources/
│   │   │   └── messages_en_US.properties
│   │   │   └── messages_de_DE.properties
│   │   └── ...
│   └── test/
│       └── ...
├── pom.xml
└── ...

Fazit

  • Branches sind ideal für die Entwicklung neuer Features, wie die Internationalisierung.
  • Für die Internationalisierung (i18n) müssen für jeder Sprache eigene messages.properties-Dateien erstellt werden.
  • ResourceBundle wird verwendet, um die Texte in der richtigen Sprache zu laden.
  • Locale wird verwendet, um die Sprache zu definieren, z.B. en-US oder de-DE
  • switchLanguage() wird verwendet, um die Sprache zu wechseln.
  • updateTexts() wird verwendet, um die GUI-Elemente mit den neuen Texten zu aktualisieren.
  • Nicht behandelt: Rechts-nach-links-Sprachen, Pluralisierung, Datums- und Zeitformate.

Datums- und Zeitformate

import java.text.DateFormat;
import java.util.Date;
import java.util.Locale;

public class DateFormatExample {
    public static void main(String[] args) {
        DateFormat dateFormat = DateFormat
        	.getDateInstance(DateFormat.LONG, Locale.GERMANY);
        System.out.println("Datum in Deutschland: " + 
        	dateFormat.format(new Date()));

        DateFormat timeFormat = DateFormat
        	.getTimeInstance(DateFormat.SHORT, Locale.UK);
        System.out.println("Uhrzeit im Vereinigten Königreich: " + 
        	timeFormat.format(new Date()));
    }
}
Datum in Deutschland: Freitag, 12. Mai 2024
Uhrzeit im Vereinigten Königreich: 15:30:00 PM

Zahlenformate

import java.text.NumberFormat;
import java.util.Locale;

public class NumberFormatExample {
    public static void main(String[] args) {
        NumberFormat numberFormat = NumberFormat
        	.getNumberInstance(Locale.FRANCE);
        System.out.println("Zahl in Frankreich: " + 
        	numberFormat.format(1234567.89));

        NumberFormat percentFormat = NumberFormat
        	.getPercentInstance(Locale.US);
        System.out.println("Prozentsatz in den USA: " + 
        	percentFormat.format(0.75));
    }
}
Zahl in Frankreich: 1 234 567,89
Prozentsatz in den USA: 75.00%

Währungsformate

import java.text.NumberFormat;
import java.util.Locale;

public class CurrencyFormatExample {
    public static void main(String[] args) {
        NumberFormat currencyFormat = NumberFormat
        	.getCurrencyInstance(Locale.JAPAN);
        System.out.println("Preis in Japan: " + 
        	currencyFormat.format(5000));
    }
}
 Preis in Japan: ¥5,000

Demo i18n mit branch

By Harald Haberstroh

Demo i18n mit branch

  • 100