Search code examples
javaswinglocalejtextfield

Is there a way to programmatically force the OS to switch language inputs in Java?


Each OS has a different scheme for changing language from keyboard or mouse. Is there any API in Java to support programmatically changing language?

What I would like is to have a translator with two JTextField objects. If I type in one, I am automatically typing in English, and if I type in the other, I would like to automatically switch to another language. If that language is Japanese or Chinese, I would like the OS to automatically switch to that language on entry to that component without having to manually switch each time. Here is some sample code using Locale and InputContext. It indicates that it succeeds in setting the context, but I type and English comes out. Contrast this with my switching to Japanese manually, where typing will result in japanese characters. What I am doing wrong?

public class TestLocale extends JFrame {
    public TestLocale() {
    super("TestLocale");
    setSize(600,600);
    JTextField a = new JTextField("English");
    JTextField b = new JTextField("Japanese");
    Locale loc =Locale.JAPANESE;
    System.out.println("Script: " + loc.getScript());
    System.out.println("Language: " + loc.getLanguage());
    b.setLocale(loc);
    b.addMouseListener(new MouseAdapter() {
        public void mouseEntered(MouseEvent e) {
            InputContext c = InputContext.getInstance();
            boolean b = c.selectInputMethod(Locale.JAPANESE);
            System.out.println("Trying to request Japanese: " + b);
        }
        } );
    add(BorderLayout.NORTH, a);
    add(BorderLayout.SOUTH, b);
    setVisible(true);
    }
    public static void main(String[] a) {
    TestLocale t = new TestLocale();
    }
}

Since Japanese is multibyte and more complex, I tried Greek. I can switch into greek right here: ασδκφξησκ (manually)

but when I select the Greek input context, nothing happens:

b.addMouseListener(new MouseAdapter() {
    public void mouseEntered(MouseEvent e) {
        InputContext c = InputContext.getInstance();
        boolean b = c.selectInputMethod(new Locale("el", "GR"));
        System.out.println("Trying to request Greek: " + b);
    }
    } );

Solution

  • Is there any API in Java to support programmatically changing language?

    Not for the operating system ...

    Indeed, on a Unix / Linux system where the locale settings are controlled by environment variables, such an API would be impossible to implement. A Unix / Linux program cannot change the environment variables of its parent shell. Even finding the "rc" files where the system / user / application has put locale variable settings is impractical.

    The best you could hope for is a bunch of operating system specific commands that will change the operating system's default locale settings, or interact with the window manager. Bear in mind that the change in the default locale setting (on many OSes) will only propagate when the user's shell restarts, etcetera.


    On the other hand, a Java program can control the input method that it uses itself to translate keyboard events into characters. For example, see InputContext.selectInputMethod.

    There are more documentation in the java.awt.im package summary javadoc.


    My question specifically asks whether I can switch input method for one JTextField. ... InputContext does not appear to be doing it ...

    The Framework document (see javadoc link) says this:

    "By default, one InputContext instance is created per Window instance, and this input context is shared by all components within the window's containment hierarchy. If necessary, components can create private input contexts. A component that doesn't have its own input context uses the one used by its parent. An input context has at most one current client component, the component that currently has the focus. When switching to a new client component, the input context calls its endComposition method to commit or cancel composed text for the previous client component."