diff --git a/tool/mlconfig/main.c b/tool/mlconfig/main.c
--- a/tool/mlconfig/main.c
+++ b/tool/mlconfig/main.c
@@ -799,6 +799,12 @@
   atexit(check_mem_leak);
 #endif
 
+  /*
+   * Loading libim-*.so after gtk im module is loaded might break internal states
+   * in gtk or input method library.
+   */
+  mc_im_init();
+
 #if !GTK_CHECK_VERSION(2, 90, 0)
   gtk_set_locale();
 #endif
diff --git a/tool/mlconfig/mc_im.c b/tool/mlconfig/mc_im.c
--- a/tool/mlconfig/mc_im.c
+++ b/tool/mlconfig/mc_im.c
@@ -55,6 +55,8 @@
 
 /* --- static variables --- */
 
+static char *cur_locale;
+
 static im_type_t im_type;
 static im_type_t cur_im_type;
 
@@ -643,9 +645,17 @@
 
 /* --- global functions --- */
 
+void mc_im_init(void) {
+  char *encoding = mc_get_str_value("encoding");
+
+  cur_locale = mc_get_str_value("locale"); /* XXX leaked */
+
+  get_im_info(cur_locale, encoding);
+
+  free(encoding);
+}
+
 GtkWidget *mc_im_config_widget_new(void) {
-  char *cur_locale = NULL;
-  char *encoding = NULL;
   char *xim_name = NULL;
   char *xim_locale = NULL;
   char *value;
@@ -659,11 +669,6 @@
   GtkWidget *radio;
   GSList *group;
 
-  cur_locale = mc_get_str_value("locale");
-  encoding = mc_get_str_value("encoding");
-
-  get_im_info(cur_locale, encoding);
-
   value = mc_get_str_value("input_method");
 
   im_name = bl_str_sep(&value, ":");
@@ -703,8 +708,6 @@
       im_opt_widget[i] = im_widget_new(i, index == i ? value : NULL, cur_locale);
   }
 
-  free(cur_locale);
-  free(encoding);
   free(im_name);
 
   frame = gtk_frame_new(_("Input Method"));
diff --git a/tool/mlconfig/mc_im.h b/tool/mlconfig/mc_im.h
--- a/tool/mlconfig/mc_im.h
+++ b/tool/mlconfig/mc_im.h
@@ -5,6 +5,8 @@
 
 #include <gtk/gtk.h>
 
+void mc_im_init(void);
+
 GtkWidget *mc_im_config_widget_new(void);
 
 void mc_update_im(void);
