If you need to provide multilingual typing (e.g., Hindi, Gujarati, Arabic, Chinese) on a webpage, the jQuery IME (Input Method Editor) library from Wikimedia is a great solution.
By default, jQuery IME attaches to an input/textarea and lets the user pick input methods. But if you want to build your own UI — for example, a custom dropdown to switch languages dynamically — you can manage the IME instance directly in JavaScript.
The following solution shows how to:
• Initialize jQuery IME on a hidden input.
• Capture keypress events and apply transliteration.
• Dynamically change languages with a dropdown ().
• Support multiple IMEs (e.g., Hindi Transliteration, Gujarati Transliteration, Arabic Buckwalter, Chinese Pinyin).
$(function() {
var LANGS = [
{ code: 'system', label: 'Use system input (OS keyboard)', native: true },
{ code: 'en', label: 'English', native: true },
{ code: 'zh', label: '中文 (Chinese) — Pinyin', native: false, imHint: /pinyin|transliteration/i },
{ code: 'gu', label: 'ગુજરાતી (Gujarati) — Transliteration', native: false, imHint: /transliteration/i },
{ code: 'hi', label: 'हिन्दी (Hindi) — Transliteration', native: false, imHint: /transliteration|inscript/i },
{ code: 'ar', label: 'العربية (Arabic) — Buckwalter', native: false, imHint: /buckwalter|transliteration/i }
];
var currentLangCode = 'en';
var currentLangObj = LANGS.find(l => l.code === currentLangCode);
var $selector = $('#language').empty();
LANGS.forEach(function(L) {
$selector.append($('<option>', { value: L.code, text: L.label }));
});
// Hidden element to initialize IME
var $el = $('<input type="text" style="position:absolute;left:-9999px;">');
if (!$el.data('ime')) {
$el.ime({ showSelector: false, imePath: './' });
}
var imeInstance = $el.data('ime');
// Default: Hindi IME
imeInstance.setLanguage('hi');
imeInstance.setIM('hi-transliteration');
// Capture keypress
$(document).on('keypress', function(e) {
var altGr = false, c, input, replacement;
var $target = $(e.target);
if (!imeInstance.inputmethod) return true;
if (e.which === 8) { // Backspace
imeInstance.context = '';
return true;
}
if (e.altKey || e.altGraphKey) altGr = true;
if ((e.which < 32 && e.which !== 13 && !altGr) || e.ctrlKey || e.metaKey) {
imeInstance.context = '';
return true;
}
c = String.fromCharCode(e.which);
var element = imeInstance.$element.get(0);
input = $target.val().slice(
Math.max(0, element.selectionStart - imeInstance.inputmethod.maxKeyLength),
$target[0].selectionStart
);
replacement = imeInstance.transliterate(input + c, imeInstance.context, altGr);
imeInstance.context = (imeInstance.context || '') + c;
if (imeInstance.context.length > imeInstance.inputmethod.contextLength) {
imeInstance.context = imeInstance.context.slice(
imeInstance.context.length - imeInstance.inputmethod.contextLength
);
}
if (replacement.noop) return true;
if (document.activeElement === $target[0]) {
var start = $target[0].selectionStart - input.length;
var end = $target[0].selectionEnd;
$target.val(
$target.val().slice(0, start) +
replacement.output +
$target.val().slice(end)
);
$target[0].selectionStart = $target[0].selectionEnd = start + replacement.output.length;
}
e.stopPropagation();
e.preventDefault();
return false;
});
// Language change handler
$selector.on('change', function() {
currentLangCode = $(this).val();
currentLangObj = LANGS.find(l => l.code === currentLangCode);
// Update IME instance
imeInstance.setLanguage(currentLangCode);
imeInstance.setIM(currentLangCode + '-transliteration');
$(':focus').trigger('focusin');
});
$selector.val('en').trigger('change');
});