i18n-swing

Swing bindings for the i18n-core internationalization framework.

This library provides locale-aware Swing components that automatically update their text, icons, fonts, mnemonics, tooltips, and accessibility attributes when the application locale changes.

Requirements

Installation

Maven

<dependency>
    <groupId>dev.javai18n</groupId>
    <artifactId>i18n-swing</artifactId>
    <version>1.2.2</version>
</dependency>

Module Declaration

module my.module
{
    requires dev.javai18n.swing;
}

Components

Localizable top-level containers

These classes serve as the locale-event source for all Resourceful components they own. They implement Localizable and dispatch locale events on the EDT when setBundleLocale() is called.

Class Extends Notes
LocalizableJFrame JFrame Standard application frame; bundle key "windowProperties" uses FramePropertyBundle
LocalizableJDialog JDialog Modal or non-modal dialog; bundle key "windowProperties" uses FramePropertyBundle
LocalizableJWindow JWindow Undecorated window; bundle key "windowProperties" uses WindowPropertyBundle

Resourceful components

All Resourceful components implement Resourceful and LocaleEventListener. Each receives an updateLocaleSpecificValues() call on the EDT whenever its source fires a locale change.

The base set of localized properties for every Resourceful component is: name, tooltip, font, accessible name, accessible description (from JComponentPropertyBundle). Additional properties are noted in the table below.

Buttons and toggles

Class Extends Additional Localized Properties
ResourcefulJButton JButton text, label, mnemonic, 7 icon types
ResourcefulJCheckBox JCheckBox text, label, mnemonic, 7 icon types
ResourcefulJRadioButton JRadioButton text, label, mnemonic, 7 icon types
ResourcefulJToggleButton JToggleButton text, label, mnemonic, 7 icon types

Menus

Class Extends Additional Localized Properties
ResourcefulJMenu JMenu text, label, mnemonic, 7 icon types
ResourcefulJMenuBar JMenuBar
ResourcefulJMenuItem JMenuItem text, label, mnemonic, 7 icon types
ResourcefulJCheckBoxMenuItem JCheckBoxMenuItem text, label, mnemonic, 7 icon types
ResourcefulJRadioButtonMenuItem JRadioButtonMenuItem text, label, mnemonic, 7 icon types
ResourcefulJPopupMenu JPopupMenu
ResourcefulJPopupMenuSeparator JPopupMenu.Separator

Text components

Class Extends Additional Localized Properties
ResourcefulJTextField JTextField
ResourcefulJTextArea JTextArea
ResourcefulJEditorPane JEditorPane
ResourcefulJTextPane JTextPane
ResourcefulJPasswordField JPasswordField
ResourcefulJFormattedTextField JFormattedTextField

Data and selection

Class Extends Additional Localized Properties
ResourcefulJComboBox JComboBox item values (string array)
ResourcefulJList JList
ResourcefulJSpinner JSpinner
ResourcefulJSlider JSlider
ResourcefulJTree JTree
ResourcefulJTable JTable
ResourcefulJTableHeader JTableHeader
ResourcefulJProgressBar JProgressBar progress string
ResourcefulJScrollBar JScrollBar
ResourcefulJColorChooser JColorChooser
ResourcefulJFileChooser JFileChooser dialog title, approve button text, approve button tooltip

Panes and containers

Class Extends Additional Localized Properties
ResourcefulJPanel JPanel
ResourcefulJScrollPane JScrollPane
ResourcefulJSplitPane JSplitPane
ResourcefulJTabbedPane JTabbedPane tab titles, tab tooltips, tab icons (per-tab via JTabbedPaneTabPropertyBundle)
ResourcefulJInternalFrame JInternalFrame title, frame icon
ResourcefulJLayeredPane JLayeredPane
ResourcefulJDesktopPane JDesktopPane
ResourcefulJDesktopIcon JDesktopIcon
ResourcefulJRootPane JRootPane
ResourcefulJViewport JViewport
ResourcefulJOptionPane JOptionPane dialog title, button option labels

Layout helpers and decorators

Class Extends Additional Localized Properties
ResourcefulBox Box
ResourcefulBoxFiller Box.Filler
ResourcefulJLabel JLabel text, mnemonic, icon, disabled icon
ResourcefulJSeparator JSeparator
ResourcefulJToolBar JToolBar
ResourcefulJToolBarSeparator JToolBar.Separator
ResourcefulJToolTip JToolTip tip text

Spinner editors

Class Extends Additional Localized Properties
ResourcefulJSpinnerDefaultEditor JSpinner.DefaultEditor
ResourcefulJSpinnerDateEditor JSpinner.DateEditor
ResourcefulJSpinnerNumberEditor JSpinner.NumberEditor
ResourcefulJSpinnerListEditor JSpinner.ListEditor

Utility menu items

Class Extends Description
LocaleJMenuItem ResourcefulJMenuItem Displays a locale name; sets the application locale when selected
LookAndFeelJMenuItem ResourcefulJMenuItem Displays a Look and Feel name; applies it when selected

Property Bundles

Property bundles are typed AttributeCollection implementations that carry the localized values read from a JSON or XML resource file. No code generation or compilation step is needed to add new bundle entries.

Bundle Extends Fields
ComponentPropertyBundle name, font, accessible name, accessible description
JComponentPropertyBundle ComponentPropertyBundle + tooltip
ButtonPropertyBundle ComponentPropertyBundle + label
AbstractButtonPropertyBundle JComponentPropertyBundle + text, label, mnemonic, icon, pressed icon, selected icon, disabled icon, disabled selected icon, rollover icon, rollover selected icon
JLabelPropertyBundle JComponentPropertyBundle + text, mnemonic, icon, disabled icon
JComboBoxPropertyBundle JComponentPropertyBundle + values (string array)
JProgressBarPropertyBundle JComponentPropertyBundle + progress string
JInternalFramePropertyBundle JComponentPropertyBundle + title, frame icon
JTabbedPaneTabPropertyBundle tab title, tab tooltip, tab icon (one entry per tab)
JOptionPanePropertyBundle JComponentPropertyBundle + title, options (string array)
JFileChooserPropertyBundle JComponentPropertyBundle + dialog title, approve button text, approve button tooltip
JToolTipPropertyBundle JComponentPropertyBundle + tip text
WindowPropertyBundle ComponentPropertyBundle + icon images (list)
FramePropertyBundle WindowPropertyBundle + title

Quick Start

1. Create a Localizable frame subclass

public class MyFrame extends LocalizableJFrame
{
    static
    {
        MyModuleRegistrar.ensureRegistered();
    }

    @Override
    public Locale[] getAvailableLocales()
    {
        return new Locale[]{ Locale.ROOT, Locale.FRANCE };
    }
}

2. Define a resource bundle

MyFrameBundle.json:

{
    "okButton":
    {
        "type": "dev.javai18n.swing.AbstractButtonPropertyBundle",
        "Text": "OK",
        "Mnemonic": 79
    }
}

MyFrameBundle_fr.json:

{
    "okButton":
    {
        "type": "dev.javai18n.swing.AbstractButtonPropertyBundle",
        "Text": "D'accord",
        "Mnemonic": 68
    }
}

3. Create a Resourceful component

MyFrame myFrame = MyFrame.create();
Resource okResource = new Resource(myFrame, "okButton");
ResourcefulJButton okButton = ResourcefulJButton.create(okResource);

The button displays the correct text, mnemonic, and other properties for the current locale. When myFrame.setBundleLocale(locale) is called, every attached Resourceful component updates itself on the Event Dispatch Thread.

Sample Application

A complete file explorer example is provided in the test sources to demonstrate the library end to end.

Main class: dev.javai18n.swing.test.TestSwingApp Frame class: dev.javai18n.swing.test.AppFrame

Launch it from an IDE or via Maven:

mvn test-compile exec:java -Dexec.classpathScope=test \
    -Dexec.mainClass=dev.javai18n.swing.test.TestSwingApp

The application starts with the system Look and Feel and opens at the user's home directory.

What it demonstrates

All localized strings live in AppFrameBundle.json and its locale variants (AppFrameBundle_en.json, AppFrameBundle_fr.json, etc.).

Building

mvn clean package

To build with sources JAR, javadoc JAR, and GPG signing for release:

mvn -Prelease clean package

Testing

To execute unit tests on the classpath (default):

mvn clean test

To execute unit tests under JPMS:

mvn clean test -Ptest-modulepath

Default Locale and Surefire

LocalizationDelegate initializes its locale field from Locale.getDefault() at construction time. Passing -Duser.language=fr to Maven on the command line does not change Locale.getDefault() in the forked Surefire JVM: Surefire propagates Maven -D system properties via System.setProperty() inside the already-running JVM, after the default locale has been initialized by the JVM startup sequence.

To ensure tests pass regardless of the OS default locale, every create() factory method in test-only Localizable classes (TestComponentSource, AppWindow, AppDialog) calls setBundleLocale(Locale.ROOT) immediately after construction. Tests that call ResourceBundle.getBundle() and assert English string values pass Locale.ROOT explicitly rather than using the no-locale overload.

When writing new tests that assert string values from a bundle, always pin the locale explicitly (e.g. setBundleLocale(Locale.ROOT)) rather than relying on Locale.getDefault().

License

This project is licensed under the Apache License, Version 2.0.