Page Menu
Home
WickedGov Phorge
Search
Configure Global Search
Log In
Files
F5968631
jquery.ime.js
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
81 KB
Referenced Files
None
Subscribers
None
jquery.ime.js
View Options
/*! jquery.ime - v0.2.0+20241001
* https://github.com/wikimedia/jquery.ime
* Copyright (c) 2024 Santhosh Thottingal; License: (GPL-2.0-or-later OR MIT) */
(
function
(
$
)
{
'use strict'
;
var
TextEntryFactory
,
TextEntry
,
FormWidgetEntry
,
ContentEditableEntry
,
defaultInputMethod
;
/**
* private function for debugging
*
* @param {jQuery} [$obj]
*/
function
debug
(
$obj
)
{
if
(
window
.
console
&&
window
.
console
.
log
)
{
window
.
console
.
log
(
$obj
);
}
}
/**
* Just initializes an empty static object.
* Similar to initClass in https://www.mediawiki.org/wiki/OOjs
*
* @param {Function} fn
*/
function
initClass
(
fn
)
{
fn
.
static
=
fn
.
static
||
{};
}
/**
* Inheritance. Uses pattern similar to OOjs (https://www.mediawiki.org/wiki/OOjs).
* Extend prototype and static methods and properties of child constructor from
* a parent constructor.
*
* @param {Function} targetFn
* @param {Function} originFn
*/
function
inheritClass
(
targetFn
,
originFn
)
{
targetFn
.
parent
=
originFn
;
targetFn
.
prototype
=
$
.
extend
(
{},
originFn
.
prototype
);
targetFn
.
prototype
.
constructor
=
originFn
.
constructor
;
targetFn
.
static
=
$
.
extend
(
{},
originFn
.
static
);
}
/**
* IME Class
*
* @class IME
* @constructor
* @param {HTMLElement} element Element on which to listen for events
* @param {TextEntry} textEntry Text entry object to use to get/set text
* @param {Object} [options]
* @param {Function} [options.helpHandler] Called for each input method row in the selector
* @param {Object} [options.helpHandler.imeSelector]
* @param {string} [options.helpHandler.ime] Id of the input method
*/
function
IME
(
element
,
textEntry
,
options
)
{
this
.
$element
=
$
(
element
);
this
.
textEntry
=
textEntry
;
// This needs to be delayed here since extending language list happens at DOM ready
$
.
ime
.
defaults
.
languages
=
Object
.
keys
(
$
.
ime
.
languages
);
this
.
options
=
$
.
extend
(
{},
$
.
ime
.
defaults
,
options
);
if
(
this
.
options
.
imePath
)
{
// Set the global IME path from the one specified to the instance
// TODO: remove this functionality and force clients to set the global
// IME path
$
.
ime
.
path
=
this
.
options
.
imePath
;
}
this
.
active
=
false
;
this
.
shifted
=
false
;
this
.
inputmethod
=
null
;
this
.
language
=
null
;
this
.
context
=
''
;
if
(
this
.
options
.
showSelector
)
{
this
.
options
.
selectorInside
=
options
.
selectorInside
!==
undefined
?
options
.
selectorInside
:
// eslint-disable-next-line no-jquery/no-class-state
this
.
$element
.
hasClass
(
'ime-position-inside'
);
this
.
selector
=
this
.
$element
.
imeselector
(
this
.
options
);
}
this
.
listen
();
}
IME
.
prototype
=
{
constructor
:
IME
,
/**
* Listen for events and bind to handlers
*/
listen
:
function
()
{
this
.
$element
.
on
(
{
'keypress.ime'
:
this
.
keypress
.
bind
(
this
),
'keyup.ime'
:
this
.
keyup
.
bind
(
this
),
'keydown.ime'
:
this
.
keydown
.
bind
(
this
),
'destroy.ime'
:
this
.
destroy
.
bind
(
this
),
'enable.ime'
:
this
.
enable
.
bind
(
this
),
'disable.ime'
:
this
.
disable
.
bind
(
this
)
}
);
},
/**
* Return a list of available language codes
*
* @return {string[]} Available language codes
*/
getLanguageCodes
:
function
()
{
return
$
.
ime
.
defaults
.
languages
;
},
/**
* Return the autonym for a language code
*
* @param {string} languageCode The language code
* @return {string|undefined} The autonym, if known
*/
getAutonym
:
function
(
languageCode
)
{
var
info
=
$
.
ime
.
languages
[
languageCode
];
return
info
&&
info
.
autonym
;
},
/**
* Return a list of available input method ids for a language
*
* @param {string} languageCode A language code
* @return {string[]} Available input method ids for that language
*/
getInputMethodIds
:
function
(
languageCode
)
{
var
info
=
$
.
ime
.
languages
[
languageCode
];
return
(
info
&&
info
.
inputmethods
)
||
[];
},
/**
* Return the name of an input method
*
* @param {string} inputMethodId The id of an input method
* @return {string} The input method's name
* @see IME#load
*/
getInputMethodName
:
function
(
inputMethodId
)
{
return
$
.
ime
.
sources
[
inputMethodId
].
name
;
},
/**
* Return a list of input method info { id: ..., name: ... } for a language.
*
* @param {string} languageCode A language code
* @return {Object[]} Info object for each available input method
*/
getInputMethods
:
function
(
languageCode
)
{
return
this
.
getInputMethodIds
(
languageCode
).
map
(
function
(
inputMethodId
)
{
return
{
id
:
inputMethodId
,
name
:
$
.
ime
.
sources
[
inputMethodId
].
name
};
}
);
},
/**
* Transliterate a given string input based on context and input method definition.
* If there are no matching rules defined, returns the original string.
*
* @param {string} input
* @param {string} context
* @param {boolean} altGr whether altGr key is pressed or not
* @return {Object} Transliteration object, with the following fields:
* "noop": boolean, whether to consider input processed or passed through;
* "output": string, the transliterated input or input unmodified.
*/
transliterate
:
function
(
input
,
context
,
altGr
)
{
var
patterns
,
regex
,
contextRegex
,
rule
,
replacement
,
i
,
retval
;
if
(
altGr
)
{
patterns
=
this
.
inputmethod
.
patterns_x
||
[];
}
else
{
patterns
=
this
.
inputmethod
.
patterns
||
[];
}
if
(
this
.
shifted
)
{
// if shift is pressed give priority for the patterns_shift
// if exists.
// Example: Shift+space where shift does not alter the keycode
patterns
=
(
this
.
inputmethod
.
patterns_shift
||
[]
)
.
concat
(
patterns
);
}
if
(
typeof
patterns
===
'function'
)
{
// For backwards compatibility, allow the rule functions to return plain
// string. Determine noop by checking whether input is different from
// output. If the rule function returns object, just return it as-is.
retval
=
patterns
.
call
(
this
,
input
,
context
);
if
(
typeof
retval
===
'string'
)
{
return
{
noop
:
input
===
retval
,
output
:
retval
};
}
return
retval
;
}
for
(
i
=
0
;
i
<
patterns
.
length
;
i
++
)
{
rule
=
patterns
[
i
];
// eslint-disable-next-line security/detect-non-literal-regexp
regex
=
new
RegExp
(
rule
[
0
]
+
'$'
);
// Last item in the rules.
// It can also be a function, because the replace
// method can have a function as the second argument.
replacement
=
rule
.
slice
(
-
1
)[
0
];
// Input string match test
if
(
regex
.
test
(
input
)
)
{
// Context test required?
if
(
rule
.
length
===
3
)
{
// eslint-disable-next-line security/detect-non-literal-regexp
contextRegex
=
new
RegExp
(
rule
[
1
]
+
'$'
);
if
(
contextRegex
.
test
(
context
)
)
{
return
{
noop
:
false
,
output
:
input
.
replace
(
regex
,
replacement
)
};
}
}
else
{
return
{
noop
:
false
,
output
:
input
.
replace
(
regex
,
replacement
)
};
}
}
}
// No matches, return the input
return
{
noop
:
true
,
output
:
input
};
},
keyup
:
function
(
e
)
{
if
(
e
.
which
===
16
)
{
// shift key
this
.
shifted
=
false
;
}
},
keydown
:
function
(
e
)
{
if
(
e
.
which
===
16
)
{
// shift key
this
.
shifted
=
true
;
}
},
/**
* Keypress handler
*
* @param {jQuery.Event} e Event
* @return {boolean}
*/
keypress
:
function
(
e
)
{
var
altGr
=
false
,
c
,
input
,
replacement
;
if
(
!
this
.
active
)
{
return
true
;
}
if
(
!
this
.
inputmethod
)
{
return
true
;
}
// handle backspace
if
(
e
.
which
===
8
)
{
// Blank the context
this
.
context
=
''
;
return
true
;
}
if
(
e
.
altKey
||
e
.
altGraphKey
)
{
altGr
=
true
;
}
// Don't process ASCII control characters except linefeed,
// as well as anything involving Ctrl, Meta and Alt,
// but do process extended keymaps
if
(
(
e
.
which
<
32
&&
e
.
which
!==
13
&&
!
altGr
)
||
e
.
ctrlKey
||
e
.
metaKey
)
{
// Blank the context
this
.
context
=
''
;
return
true
;
}
c
=
String
.
fromCharCode
(
e
.
which
);
// Append the character being typed to the preceding few characters,
// to provide context for the transliteration regexes.
input
=
this
.
textEntry
.
getTextBeforeSelection
(
this
.
inputmethod
.
maxKeyLength
);
replacement
=
this
.
transliterate
(
input
+
c
,
this
.
context
,
altGr
);
// Update the context
this
.
context
+=
c
;
if
(
this
.
context
.
length
>
this
.
inputmethod
.
contextLength
)
{
// The buffer is longer than needed, truncate it at the front
this
.
context
=
this
.
context
.
slice
(
this
.
context
.
length
-
this
.
inputmethod
.
contextLength
);
}
// Allow rules to explicitly define whether we match something.
// Otherwise we cannot distinguish between no matching rule and
// rule that provides identical output but consumes the event
// to prevent normal behavior. See Udmurt layout which uses
// altgr rules to allow typing the original character.
if
(
replacement
.
noop
)
{
return
true
;
}
this
.
textEntry
.
replaceTextAtSelection
(
input
.
length
,
replacement
.
output
);
e
.
stopPropagation
();
return
false
;
},
/**
* Check whether the input method is active or not
*
* @return {boolean}
*/
isActive
:
function
()
{
return
this
.
active
;
},
/**
* Disable the input method
*/
disable
:
function
()
{
this
.
active
=
false
;
$
.
ime
.
preferences
.
setIM
(
'system'
);
},
/**
* Enable the input method
*/
enable
:
function
()
{
this
.
active
=
true
;
},
/**
* Toggle the active state of input method
*/
toggle
:
function
()
{
this
.
active
=
!
this
.
active
;
},
/**
* Destroy the binding of ime to the editable element
*/
destroy
:
function
()
{
$
(
document
.
body
).
off
(
'.ime'
);
this
.
$element
.
off
(
'.ime'
).
removeData
(
'ime'
).
removeData
(
'imeselector'
);
},
/**
* Get the current input method
*
* @return {string} Current input method id
*/
getIM
:
function
()
{
return
this
.
inputmethod
;
},
/**
* Set the current input method
*
* @param {string} inputmethodId
*/
setIM
:
function
(
inputmethodId
)
{
this
.
inputmethod
=
$
.
ime
.
inputmethods
[
inputmethodId
];
$
.
ime
.
preferences
.
setIM
(
inputmethodId
);
this
.
$element
.
trigger
(
'imeMethodChange'
);
},
/**
* Set the current Language
*
* @param {string} languageCode
* @return {boolean}
*/
setLanguage
:
function
(
languageCode
)
{
if
(
!
$
.
ime
.
languages
[
languageCode
]
)
{
debug
(
'Language '
+
languageCode
+
' is not known to jquery.ime.'
);
return
false
;
}
this
.
language
=
languageCode
;
$
.
ime
.
preferences
.
setLanguage
(
languageCode
);
this
.
$element
.
trigger
(
'imeLanguageChange'
);
return
true
;
},
/**
* Get current language
*
* @return {string}
*/
getLanguage
:
function
()
{
return
this
.
language
;
},
/**
* load an input method by given id
*
* @param {string} inputmethodId
* @return {jQuery.Promise}
*/
load
:
function
(
inputmethodId
)
{
return
$
.
ime
.
load
(
inputmethodId
);
}
};
/**
* TextEntry factory
*
* @class TextEntryFactory
* @constructor
*/
TextEntryFactory
=
function
IMETextEntryFactory
()
{
this
.
TextEntryClasses
=
[];
};
/* Inheritance */
initClass
(
TextEntryFactory
);
/* Methods */
/**
* Register a TextEntry class, with priority over previous registrations
*
* @param {TextEntry} TextEntryClass Class to register
*/
TextEntryFactory
.
prototype
.
register
=
function
(
TextEntryClass
)
{
this
.
TextEntryClasses
.
unshift
(
TextEntryClass
);
};
/**
* Wrap an editable element with the appropriate TextEntry class
*
* @param {jQuery} $element The element to wrap
* @return {TextEntry|null} A TextEntry, or null if no match
*/
TextEntryFactory
.
prototype
.
wrap
=
function
(
$element
)
{
var
i
,
len
,
TextEntryClass
;
// eslint-disable-next-line no-jquery/no-class-state
if
(
$element
.
hasClass
(
'noime'
)
)
{
return
null
;
}
for
(
i
=
0
,
len
=
this
.
TextEntryClasses
.
length
;
i
<
len
;
i
++
)
{
TextEntryClass
=
this
.
TextEntryClasses
[
i
];
if
(
TextEntryClass
.
static
.
canWrap
(
$element
)
)
{
return
new
TextEntryClass
(
$element
);
}
}
return
null
;
};
/* Initialization */
TextEntryFactory
.
static
.
singleton
=
new
TextEntryFactory
();
/**
* Generic text entry
*
* @class TextEntry
* @abstract
*/
TextEntry
=
function
IMETextEntry
()
{
};
/* Inheritance */
initClass
(
TextEntry
);
/* Static methods */
/**
* Test whether can wrap this type of element
*
* @param {jQuery} $element The element to wrap
* @return {boolean} Whether the element can be wrapped
*/
TextEntry
.
static
.
canWrap
=
function
()
{
return
false
;
};
/* Abstract methods */
/**
* Get text immediately before the current selection start.
*
* This SHOULD return the empty string for non-collapsed selections.
*
* @param {number} maxLength Maximum number of chars (code units) to return
* @return {string} Up to maxLength of text
*/
TextEntry
.
prototype
.
getTextBeforeSelection
=
null
;
/**
* Replace the currently selected text and/or text before the selection
*
* @param {number} precedingCharCount Number of chars before selection to replace
* @param {string} newText Replacement text
*/
TextEntry
.
prototype
.
replaceTextAtSelection
=
null
;
/**
* TextEntry class for input/textarea widgets
*
* @class FormWidgetEntry
* @constructor
* @param {jQuery} $element The element to wrap
*/
FormWidgetEntry
=
function
IMEFormWidgetEntry
(
$element
)
{
this
.
$element
=
$element
;
};
/* Inheritance */
inheritClass
(
FormWidgetEntry
,
TextEntry
);
/* Static methods */
/**
* @inheritdoc TextEntry
*/
FormWidgetEntry
.
static
.
canWrap
=
function
(
$element
)
{
return
$element
.
is
(
'input:not([type]), input[type=text], input[type=search], textarea'
)
&&
!
$element
.
prop
(
'readonly'
)
&&
!
$element
.
prop
(
'disabled'
);
};
/* Instance methods */
/**
* @inheritdoc TextEntry
*/
FormWidgetEntry
.
prototype
.
getTextBeforeSelection
=
function
(
maxLength
)
{
var
element
=
this
.
$element
.
get
(
0
);
return
this
.
$element
.
val
().
slice
(
Math
.
max
(
0
,
element
.
selectionStart
-
maxLength
),
element
.
selectionStart
);
};
/**
* @inheritdoc TextEntry
*/
FormWidgetEntry
.
prototype
.
replaceTextAtSelection
=
function
(
precedingCharCount
,
newText
)
{
var
element
=
this
.
$element
.
get
(
0
),
start
=
element
.
selectionStart
,
scrollTop
=
element
.
scrollTop
;
// Replace the whole text of the text area:
// text before + newText + text after.
// This could be made better if range selection worked on browsers.
// But for complex scripts, browsers place cursor in unexpected places
// and it's not possible to fix cursor programmatically.
// Ref Bug https://bugs.webkit.org/show_bug.cgi?id=66630
element
.
value
=
element
.
value
.
slice
(
0
,
start
-
precedingCharCount
)
+
newText
+
element
.
value
.
slice
(
element
.
selectionEnd
,
element
.
value
.
length
);
// Emit an event so that input fields that rely on events
// work properly
element
.
dispatchEvent
(
new
Event
(
'input'
)
);
// restore scroll
element
.
scrollTop
=
scrollTop
;
// set selection
element
.
selectionStart
=
element
.
selectionEnd
=
start
-
precedingCharCount
+
newText
.
length
;
};
TextEntryFactory
.
static
.
singleton
.
register
(
FormWidgetEntry
);
/**
* TextEntry class for ContentEditable
*
* @class ContentEditableEntry
* @constructor
* @param {jQuery} $element The element to wrap
*/
ContentEditableEntry
=
function
IMEContentEditableEntry
(
$element
)
{
this
.
$element
=
$element
;
};
/* Inheritance */
inheritClass
(
ContentEditableEntry
,
TextEntry
);
/* Static methods */
/**
* @inheritdoc TextEntry
*/
ContentEditableEntry
.
static
.
canWrap
=
function
(
$element
)
{
return
$element
.
is
(
'[contenteditable]'
);
};
/* Instance methods */
/**
* @inheritdoc TextEntry
*/
ContentEditableEntry
.
prototype
.
getTextBeforeSelection
=
function
(
maxLength
)
{
var
range
=
this
.
getSelectedRange
();
if
(
!
range
||
!
range
.
collapsed
||
range
.
startContainer
.
nodeType
!==
Node
.
TEXT_NODE
)
{
return
''
;
}
return
range
.
startContainer
.
nodeValue
.
slice
(
Math
.
max
(
0
,
range
.
startOffset
-
maxLength
),
range
.
startOffset
);
};
/**
* @inheritdoc SelectionWrapper
*/
ContentEditableEntry
.
prototype
.
replaceTextAtSelection
=
function
(
precedingCharCount
,
newText
)
{
var
textNode
,
textOffset
,
newOffset
,
newRange
,
sel
=
window
.
getSelection
(),
range
=
this
.
getSelectedRange
();
if
(
!
range
)
{
return
;
}
// Trigger any externally registered jQuery compositionstart event listeners.
// TODO: Try node.dispatchEvent( new CompositionEvent(...) ) so listeners not
// registered using jQuery will also get triggered, then fallback gracefully for
// browsers that do not support it.
this
.
$element
.
trigger
(
'compositionstart'
);
if
(
!
range
.
collapsed
)
{
range
.
deleteContents
();
}
newRange
=
document
.
createRange
();
if
(
range
.
startContainer
.
nodeType
===
Node
.
TEXT_NODE
)
{
// Alter this text node's content and move the cursor
textNode
=
range
.
startContainer
;
textOffset
=
range
.
startOffset
;
textNode
.
nodeValue
=
textNode
.
nodeValue
.
slice
(
0
,
Math
.
max
(
0
,
textOffset
-
precedingCharCount
)
)
+
newText
+
textNode
.
nodeValue
.
slice
(
textOffset
);
newOffset
=
textOffset
-
precedingCharCount
+
newText
.
length
;
newRange
.
setStart
(
range
.
startContainer
,
newOffset
);
newRange
.
setEnd
(
range
.
startContainer
,
newOffset
);
}
else
{
// XXX assert precedingCharCount === 0
// Insert a new text node with the new text
textNode
=
document
.
createTextNode
(
newText
);
range
.
startContainer
.
insertBefore
(
textNode
,
range
.
startContainer
.
childNodes
[
range
.
startOffset
]
);
newRange
.
setStart
(
textNode
,
textNode
.
length
);
newRange
.
setEnd
(
textNode
,
textNode
.
length
);
}
sel
.
removeAllRanges
();
sel
.
addRange
(
newRange
);
// Trigger any externally registered jQuery compositionend / input event listeners.
// TODO: Try node.dispatchEvent( new CompositionEvent(...) ) so listeners not
// registered using jQuery will also get triggered, then fallback gracefully for
// browsers that do not support it.
this
.
$element
.
trigger
(
'compositionend'
);
this
.
$element
.
trigger
(
'input'
);
};
/**
* Get the selection range inside the wrapped element, or null
*
* @return {Range|null} The selection range
*/
ContentEditableEntry
.
prototype
.
getSelectedRange
=
function
()
{
var
range
,
sel
=
window
.
getSelection
();
if
(
sel
.
rangeCount
===
0
)
{
return
null
;
}
range
=
sel
.
getRangeAt
(
0
);
if
(
!
this
.
$element
[
0
].
contains
(
range
.
commonAncestorContainer
)
)
{
return
null
;
}
return
range
;
};
TextEntryFactory
.
static
.
singleton
.
register
(
ContentEditableEntry
);
/* Exports */
/**
* jQuery plugin ime
*
* @param {Object} option
* @return {jQuery}
*/
$
.
fn
.
ime
=
function
(
option
)
{
return
this
.
each
(
function
()
{
var
data
,
textEntry
,
$this
=
$
(
this
),
options
=
typeof
option
===
'object'
&&
option
;
data
=
$this
.
data
(
'ime'
);
if
(
!
data
)
{
textEntry
=
TextEntryFactory
.
static
.
singleton
.
wrap
(
$this
);
if
(
!
textEntry
)
{
return
;
}
data
=
new
IME
(
this
,
textEntry
,
options
);
$this
.
data
(
'ime'
,
data
);
}
if
(
typeof
option
===
'string'
)
{
data
[
option
]();
}
}
);
};
$
.
ime
=
{};
$
.
ime
.
inputmethods
=
{};
$
.
ime
.
sources
=
{};
$
.
ime
.
preferences
=
{};
$
.
ime
.
languages
=
{};
/**
* @property {string} Relative or absolute path for the rules folder of jquery.ime
*/
$
.
ime
.
path
=
'../'
;
$
.
ime
.
textEntryFactory
=
TextEntryFactory
.
static
.
singleton
;
$
.
ime
.
TextEntry
=
TextEntry
;
$
.
ime
.
inheritClass
=
inheritClass
;
defaultInputMethod
=
{
contextLength
:
0
,
maxKeyLength
:
1
};
/**
* load an input method by given id
*
* @param {string} inputmethodId
* @return {jQuery.Promise}
*/
$
.
ime
.
load
=
function
(
inputmethodId
)
{
var
dependency
,
deferred
=
$
.
Deferred
();
if
(
$
.
ime
.
inputmethods
[
inputmethodId
]
)
{
return
deferred
.
resolve
();
}
// Validate the input method id.
if
(
!
$
.
ime
.
sources
[
inputmethodId
]
)
{
return
deferred
.
reject
();
}
dependency
=
$
.
ime
.
sources
[
inputmethodId
].
depends
;
if
(
dependency
&&
!
$
.
ime
.
inputmethods
[
dependency
]
)
{
$
.
ime
.
load
(
dependency
).
done
(
function
()
{
$
.
ime
.
load
(
inputmethodId
).
done
(
function
()
{
deferred
.
resolve
();
}
);
}
);
return
deferred
;
}
debug
(
'Loading '
+
inputmethodId
);
deferred
=
$
.
ajax
(
{
url
:
$
.
ime
.
path
+
$
.
ime
.
sources
[
inputmethodId
].
source
,
dataType
:
'script'
,
cache
:
true
}
).
done
(
function
()
{
debug
(
inputmethodId
+
' loaded'
);
}
).
fail
(
function
(
jqxhr
,
settings
,
exception
)
{
debug
(
'Error in loading inputmethod '
+
inputmethodId
+
' Exception: '
+
exception
);
}
);
return
deferred
.
promise
();
};
$
.
ime
.
register
=
function
(
inputMethod
)
{
$
.
ime
.
inputmethods
[
inputMethod
.
id
]
=
$
.
extend
(
{},
defaultInputMethod
,
inputMethod
);
};
/**
* Set the relative/absolute path to rules/ (for loading input methods)
*
* @param {string} path The relative/absolute path in which rules/ lies
*/
$
.
ime
.
setPath
=
function
(
path
)
{
$
.
ime
.
path
=
path
;
};
// default options
$
.
ime
.
defaults
=
{
languages
:
[],
// Languages to be used- by default all languages
helpHandler
:
null
,
// Called for each ime option in the menu
showSelector
:
true
,
selectorInside
:
undefined
// If not set will check if '.ime-position-inside' class is preset
};
}(
jQuery
)
);
(
function
(
$
)
{
'use strict'
;
var
selectorTemplate
,
MutationObserver
;
function
IMESelector
(
element
,
options
)
{
this
.
$element
=
$
(
element
);
this
.
options
=
$
.
extend
(
{},
IMESelector
.
defaults
,
options
);
this
.
active
=
false
;
this
.
$imeSetting
=
null
;
this
.
$menu
=
null
;
this
.
inputmethod
=
null
;
this
.
timer
=
null
;
this
.
init
();
this
.
listen
();
}
function
languageListTitle
()
{
return
$
(
'<h3>'
)
.
addClass
(
'ime-lang-title'
)
.
attr
(
'data-i18n'
,
'jquery-ime-other-languages'
)
.
text
(
'Other languages'
);
}
function
imeList
()
{
return
$
(
'<ul>'
).
addClass
(
'ime-list'
);
}
function
imeListTitle
()
{
return
$
(
'<h3>'
).
addClass
(
'ime-list-title autonym'
);
}
function
toggleMenuItem
()
{
return
$
(
'<div>'
).
addClass
(
'ime-disable selectable-row'
).
append
(
$
(
'<span>'
)
.
addClass
(
'ime-disable-link'
)
.
addClass
(
'ime-checked'
)
.
attr
(
'data-i18n'
,
'jquery-ime-disable-text'
)
.
text
(
'System input method'
),
$
(
'<span>'
)
.
addClass
(
'ime-disable-shortcut'
)
.
text
(
'CTRL+M'
)
);
}
/**
* Check whether a keypress event corresponds to the shortcut key
*
* @param {event} event
* @return {boolean} true if the key is a shortcut key
*/
function
isShortcutKey
(
event
)
{
// 77 - The letter M, for Ctrl-M
return
event
.
ctrlKey
&&
!
event
.
altKey
&&
(
event
.
which
===
77
);
}
IMESelector
.
prototype
=
{
constructor
:
IMESelector
,
init
:
function
()
{
this
.
prepareSelectorMenu
();
this
.
position
();
this
.
$imeSetting
.
hide
();
},
prepareSelectorMenu
:
function
()
{
// TODO: In this approach there is a menu for each editable area.
// With correct event mapping we can probably reduce it to one menu.
this
.
$imeSetting
=
$
(
selectorTemplate
);
this
.
$menu
=
$
(
'<div>'
).
addClass
(
'imeselector-menu'
).
attr
(
'role'
,
'menu'
);
this
.
$menu
.
append
(
imeListTitle
(),
imeList
(),
toggleMenuItem
(),
languageListTitle
()
);
this
.
prepareLanguageList
();
this
.
$menu
.
append
(
this
.
helpLink
()
);
if
(
$
.
i18n
)
{
this
.
$menu
.
i18n
();
}
this
.
$imeSetting
.
append
(
this
.
$menu
);
$
(
document
.
body
).
append
(
this
.
$imeSetting
);
},
stopTimer
:
function
()
{
if
(
this
.
timer
)
{
clearTimeout
(
this
.
timer
);
this
.
timer
=
null
;
}
this
.
$imeSetting
.
stop
(
true
,
true
);
},
resetTimer
:
function
()
{
var
imeselector
=
this
;
this
.
stopTimer
();
this
.
timer
=
setTimeout
(
function
()
{
// TODO: Use CSS transitions
// eslint-disable-next-line no-jquery/no-animate
imeselector
.
$imeSetting
.
animate
(
{
opacity
:
0
,
marginTop
:
'-20px'
},
500
,
function
()
{
imeselector
.
$imeSetting
.
hide
();
// Restore properties for the next time it becomes visible:
imeselector
.
$imeSetting
.
css
(
'opacity'
,
1
);
imeselector
.
$imeSetting
.
css
(
'margin-top'
,
0
);
}
);
},
this
.
options
.
timeout
);
},
focus
:
function
()
{
// Hide all other IME settings and collapse open menus
// eslint-disable-next-line no-jquery/no-global-selector
$
(
'div.imeselector'
).
hide
();
// eslint-disable-next-line no-jquery/no-global-selector
$
(
'div.imeselector-menu'
).
removeClass
(
'ime-open'
);
this
.
afterKeydown
();
},
afterKeydown
:
function
()
{
this
.
$imeSetting
.
show
();
this
.
resetTimer
();
},
show
:
function
()
{
this
.
$menu
.
addClass
(
'ime-open'
);
this
.
stopTimer
();
this
.
$imeSetting
.
show
();
return
false
;
},
hide
:
function
()
{
this
.
$menu
.
removeClass
(
'ime-open'
);
this
.
resetTimer
();
return
false
;
},
toggle
:
function
()
{
// eslint-disable-next-line no-jquery/no-class-state
if
(
this
.
$menu
.
hasClass
(
'ime-open'
)
)
{
this
.
hide
();
}
else
{
this
.
show
();
}
},
/**
* Bind the events and listen
*/
listen
:
function
()
{
var
imeselector
=
this
;
imeselector
.
$imeSetting
.
on
(
'click.ime'
,
function
(
e
)
{
var
$t
=
$
(
e
.
target
);
// eslint-disable-next-line no-jquery/no-class-state
if
(
$t
.
hasClass
(
'imeselector-toggle'
)
)
{
imeselector
.
toggle
();
}
return
false
;
}
);
imeselector
.
$element
.
on
(
'blur.ime'
,
function
()
{
// eslint-disable-next-line no-jquery/no-class-state
if
(
!
imeselector
.
$imeSetting
.
hasClass
(
'ime-onfocus'
)
)
{
imeselector
.
$imeSetting
.
hide
();
imeselector
.
hide
();
}
}
);
// Hide the menu when clicked outside
$
(
document
.
body
).
on
(
'click'
,
function
()
{
imeselector
.
hide
();
}
);
// ... but when clicked on window do not propagate it.
this
.
$menu
.
on
(
'click'
,
function
(
event
)
{
event
.
stopPropagation
();
}
);
imeselector
.
$imeSetting
.
on
(
'mouseenter'
,
function
()
{
// We don't want the selector to disappear
// while the user is trying to click it
imeselector
.
stopTimer
();
imeselector
.
$imeSetting
.
addClass
(
'ime-onfocus'
);
}
).
on
(
'mouseleave'
,
function
()
{
imeselector
.
resetTimer
();
imeselector
.
$imeSetting
.
removeClass
(
'ime-onfocus'
);
}
);
imeselector
.
$menu
.
on
(
'click.ime'
,
'li'
,
function
()
{
imeselector
.
$element
.
trigger
(
'focus'
);
return
false
;
}
);
imeselector
.
$menu
.
on
(
'click.ime'
,
'li.ime-im'
,
function
()
{
imeselector
.
selectIM
(
$
(
this
).
data
(
'ime-inputmethod'
)
);
imeselector
.
$element
.
trigger
(
'setim.ime'
,
$
(
this
).
data
(
'ime-inputmethod'
)
);
return
false
;
}
);
imeselector
.
$menu
.
on
(
'click.ime'
,
'li.ime-lang'
,
function
()
{
var
im
=
imeselector
.
selectLanguage
(
$
(
this
).
attr
(
'lang'
)
);
imeselector
.
$element
.
trigger
(
'setim.ime'
,
im
);
return
false
;
}
);
imeselector
.
$menu
.
on
(
'click.ime'
,
'div.ime-disable'
,
function
()
{
imeselector
.
disableIM
();
return
false
;
}
);
// Just make it work as a regular link
imeselector
.
$menu
.
on
(
'click.ime'
,
'.ime-help-link'
,
function
(
e
)
{
e
.
stopPropagation
();
}
);
imeselector
.
$element
.
on
(
'focus.ime'
,
function
(
e
)
{
imeselector
.
selectLanguage
(
imeselector
.
decideLanguage
()
);
imeselector
.
focus
();
e
.
stopPropagation
();
}
);
imeselector
.
$element
.
attrchange
(
function
()
{
// eslint-disable-next-line no-jquery/no-sizzle
if
(
imeselector
.
$element
.
is
(
':hidden'
)
)
{
imeselector
.
$imeSetting
.
hide
();
}
}
);
// Possible resize of textarea
imeselector
.
$element
.
on
(
{
'mouseup.ime'
:
this
.
position
.
bind
(
this
),
'keydown.ime'
:
this
.
keydown
.
bind
(
this
)
}
);
// Update IM selector position when the window is resized
// or the browser window is zoomed in or zoomed out
$
(
window
).
on
(
'resize'
,
function
()
{
imeselector
.
position
();
}
);
},
/**
* Keydown event handler. Handles shortcut key presses
*
* @param {jQuery.Event} e
* @return {boolean}
*/
keydown
:
function
(
e
)
{
var
ime
=
$
(
e
.
target
).
data
(
'ime'
),
firstInputmethod
,
previousInputMethods
,
languageCode
;
this
.
afterKeydown
();
// shows the trigger in case it is hidden
if
(
isShortcutKey
(
e
)
)
{
if
(
ime
.
isActive
()
)
{
this
.
disableIM
();
this
.
$element
.
trigger
(
'setim.ime'
,
'system'
);
}
else
{
if
(
this
.
inputmethod
!==
null
)
{
this
.
selectIM
(
this
.
inputmethod
.
id
);
this
.
$element
.
trigger
(
'setim.ime'
,
this
.
inputmethod
.
id
);
}
else
{
languageCode
=
this
.
decideLanguage
();
this
.
selectLanguage
(
languageCode
);
if
(
!
ime
.
isActive
()
&&
$
.
ime
.
languages
[
languageCode
]
)
{
// Even after pressing toggle shortcut again, it is still disabled
// Check if there is a previously used input method.
previousInputMethods
=
$
.
ime
.
preferences
.
getPreviousInputMethods
();
if
(
previousInputMethods
[
0
]
)
{
this
.
selectIM
(
previousInputMethods
[
0
]
);
}
else
{
// Provide the default input method in this case.
firstInputmethod
=
$
.
ime
.
languages
[
languageCode
].
inputmethods
[
0
];
this
.
selectIM
(
firstInputmethod
);
}
}
}
}
e
.
preventDefault
();
e
.
stopPropagation
();
return
false
;
}
return
true
;
},
/**
* Position the im selector relative to the edit area
*/
position
:
function
()
{
var
menuWidth
,
menuTop
,
menuLeft
,
elementPosition
,
top
,
left
,
cssTop
,
cssLeft
,
verticalRoom
,
overflowsOnRight
,
imeSelector
=
this
,
rtlElement
=
this
.
$element
.
css
(
'direction'
)
===
'rtl'
,
$window
=
$
(
window
);
this
.
focus
();
// shows the trigger in case it is hidden
elementPosition
=
this
.
$element
.
offset
();
top
=
elementPosition
.
top
+
this
.
$element
.
outerHeight
();
left
=
elementPosition
.
left
;
// RTL element position fix
if
(
!
rtlElement
)
{
left
=
elementPosition
.
left
+
this
.
$element
.
outerWidth
()
-
this
.
$imeSetting
.
outerWidth
();
}
if
(
this
.
options
.
selectorInside
)
{
top
-=
this
.
$imeSetting
.
outerHeight
();
}
// While determining whether to place the selector above or below the input box,
// take into account the value of scrollTop, to avoid the selector from always
// getting placed above the input box since window.height would be less than top
// if the page has been scrolled.
verticalRoom
=
$window
.
height
()
+
$
(
document
).
scrollTop
()
-
top
;
if
(
verticalRoom
<
this
.
$imeSetting
.
outerHeight
()
)
{
top
=
elementPosition
.
top
-
this
.
$imeSetting
.
outerHeight
();
if
(
this
.
options
.
selectorInside
)
{
top
+=
this
.
$imeSetting
.
outerHeight
();
}
menuTop
=
this
.
$menu
.
outerHeight
()
+
this
.
$imeSetting
.
outerHeight
();
// Flip the menu to the top only if it can fit in the space there
if
(
menuTop
<
top
)
{
this
.
$menu
.
addClass
(
'ime-position-top'
)
.
css
(
'top'
,
-
menuTop
);
}
}
cssTop
=
top
;
cssLeft
=
left
;
this
.
$element
.
parents
().
each
(
function
()
{
if
(
$
(
this
).
css
(
'position'
)
===
'fixed'
)
{
imeSelector
.
$imeSetting
.
css
(
'position'
,
'fixed'
);
cssTop
-=
$
(
document
).
scrollTop
();
cssLeft
-=
$
(
document
).
scrollLeft
();
return
false
;
}
}
);
this
.
$imeSetting
.
css
(
{
top
:
cssTop
,
left
:
cssLeft
}
);
menuWidth
=
this
.
$menu
.
width
();
overflowsOnRight
=
(
left
-
$
(
document
).
scrollLeft
()
+
menuWidth
)
>
$window
.
width
();
// Adjust horizontal position if there's
// not enough space on any side
if
(
menuWidth
>
left
||
rtlElement
&&
overflowsOnRight
)
{
if
(
rtlElement
)
{
if
(
overflowsOnRight
)
{
this
.
$menu
.
addClass
(
'ime-right'
);
menuLeft
=
this
.
$imeSetting
.
outerWidth
()
-
menuWidth
;
}
else
{
menuLeft
=
0
;
}
}
else
{
this
.
$menu
.
addClass
(
'ime-right'
);
menuLeft
=
elementPosition
.
left
;
}
this
.
$menu
.
css
(
'left'
,
menuLeft
);
}
},
/**
* Select a language
*
* @param {string} languageCode
* @return {string|boolean} Selected input method id or false
*/
selectLanguage
:
function
(
languageCode
)
{
var
ime
,
imePref
,
language
;
// consider language codes case insensitive
languageCode
=
languageCode
&&
languageCode
.
toLowerCase
();
ime
=
this
.
$element
.
data
(
'ime'
);
imePref
=
$
.
ime
.
preferences
.
getIM
(
languageCode
);
language
=
$
.
ime
.
languages
[
languageCode
];
this
.
setMenuTitle
(
this
.
getAutonym
(
languageCode
)
);
if
(
!
language
)
{
return
false
;
}
if
(
ime
.
getLanguage
()
===
languageCode
)
{
// Nothing to do. It is same as the current language,
// but check whether the input method changed.
if
(
ime
.
inputmethod
&&
ime
.
inputmethod
.
id
!==
imePref
)
{
this
.
selectIM
(
$
.
ime
.
preferences
.
getIM
(
languageCode
)
);
}
return
$
.
ime
.
preferences
.
getIM
(
languageCode
);
}
this
.
$menu
.
find
(
'li.ime-lang'
).
show
();
this
.
$menu
.
find
(
'li[lang='
+
languageCode
+
']'
).
hide
();
this
.
prepareInputMethods
(
languageCode
);
this
.
hide
();
// And select the default inputmethod
ime
.
setLanguage
(
languageCode
);
this
.
inputmethod
=
null
;
this
.
selectIM
(
$
.
ime
.
preferences
.
getIM
(
languageCode
)
);
return
$
.
ime
.
preferences
.
getIM
(
languageCode
);
},
/**
* Get the autonym by language code.
*
* @param {string} languageCode
* @return {string} The autonym
*/
getAutonym
:
function
(
languageCode
)
{
return
$
.
ime
.
languages
[
languageCode
]
&&
$
.
ime
.
languages
[
languageCode
].
autonym
;
},
/**
* Set the title of the selector menu.
*
* @param {string} title
*/
setMenuTitle
:
function
(
title
)
{
this
.
$menu
.
find
(
'.ime-list-title'
).
text
(
title
);
},
/**
* Decide on initial language to select
*
* @return {string}
*/
decideLanguage
:
function
()
{
if
(
$
.
ime
.
preferences
.
getLanguage
()
)
{
// There has been an override by the user,
// so return the language selected by user
return
$
.
ime
.
preferences
.
getLanguage
();
}
if
(
this
.
$element
.
attr
(
'lang'
)
&&
$
.
ime
.
languages
[
this
.
$element
.
attr
(
'lang'
)
]
)
{
return
this
.
$element
.
attr
(
'lang'
);
}
// There is either no IMs for the given language attr
// or there is no lang attr at all.
return
$
.
ime
.
preferences
.
getDefaultLanguage
();
},
/**
* Select an input method
*
* @param {string} inputmethodId
*/
selectIM
:
function
(
inputmethodId
)
{
var
imeselector
=
this
,
ime
;
if
(
!
inputmethodId
)
{
return
;
}
this
.
$menu
.
find
(
'.ime-checked'
).
removeClass
(
'ime-checked'
);
this
.
$menu
.
find
(
'li[data-ime-inputmethod='
+
inputmethodId
+
']'
)
.
addClass
(
'ime-checked'
);
ime
=
this
.
$element
.
data
(
'ime'
);
if
(
inputmethodId
===
'system'
)
{
this
.
disableIM
();
return
;
}
ime
.
load
(
inputmethodId
).
done
(
function
()
{
imeselector
.
inputmethod
=
$
.
ime
.
inputmethods
[
inputmethodId
];
imeselector
.
hide
();
ime
.
enable
();
ime
.
setIM
(
inputmethodId
);
imeselector
.
$imeSetting
.
find
(
'a.ime-name'
).
text
(
$
.
ime
.
sources
[
inputmethodId
].
name
);
imeselector
.
position
();
// Save this preference
$
.
ime
.
preferences
.
save
();
}
);
},
/**
* Disable the inputmethods (Use the system input method)
*/
disableIM
:
function
()
{
this
.
$menu
.
find
(
'.ime-checked'
).
removeClass
(
'ime-checked'
);
this
.
$menu
.
find
(
'div.ime-disable'
).
addClass
(
'ime-checked'
);
this
.
$element
.
data
(
'ime'
).
disable
();
this
.
$imeSetting
.
find
(
'a.ime-name'
).
text
(
''
);
this
.
hide
();
this
.
position
();
// Save this preference
$
.
ime
.
preferences
.
save
();
},
/**
* Prepare language list
*/
prepareLanguageList
:
function
()
{
var
languageCodeIndex
,
$languageListWrapper
,
$languageList
,
languageList
,
$languageItem
,
$language
,
languageCode
,
language
;
// Language list can be very long, so we use a container with
// overflow auto
$languageListWrapper
=
$
(
'<div>'
).
addClass
(
'ime-language-list-wrapper'
);
$languageList
=
$
(
'<ul>'
).
addClass
(
'ime-language-list'
);
if
(
typeof
this
.
options
.
languages
===
'function'
)
{
languageList
=
this
.
options
.
languages
();
}
else
{
languageList
=
this
.
options
.
languages
;
}
for
(
languageCodeIndex
in
languageList
)
{
languageCode
=
languageList
[
languageCodeIndex
];
language
=
$
.
ime
.
languages
[
languageCode
];
if
(
!
language
)
{
continue
;
}
$languageItem
=
$
(
'<a>'
)
.
attr
(
'href'
,
'#'
)
.
text
(
this
.
getAutonym
(
languageCode
)
)
.
addClass
(
'selectable-row-item autonym'
);
$language
=
$
(
'<li>'
).
addClass
(
'ime-lang selectable-row'
).
attr
(
'lang'
,
languageCode
);
$language
.
append
(
$languageItem
);
$languageList
.
append
(
$language
);
}
$languageListWrapper
.
append
(
$languageList
);
this
.
$menu
.
append
(
$languageListWrapper
);
if
(
this
.
options
.
languageSelector
)
{
this
.
$menu
.
append
(
this
.
options
.
languageSelector
()
);
}
},
/**
* Prepare input methods in menu for the given language code
*
* @param {string} languageCode
*/
prepareInputMethods
:
function
(
languageCode
)
{
var
language
=
$
.
ime
.
languages
[
languageCode
],
$imeList
=
this
.
$menu
.
find
(
'.ime-list'
),
imeSelector
=
this
;
$imeList
.
empty
();
language
.
inputmethods
.
forEach
(
function
(
inputmethod
)
{
var
$imeItem
,
$inputMethod
,
source
,
name
;
source
=
$
.
ime
.
sources
[
inputmethod
];
if
(
!
source
)
{
return
;
}
name
=
source
.
name
;
$imeItem
=
$
(
'<a>'
)
.
attr
(
'href'
,
'#'
)
.
text
(
name
)
.
addClass
(
'selectable-row-item'
);
$inputMethod
=
$
(
'<li>'
)
.
attr
(
'data-ime-inputmethod'
,
inputmethod
)
.
addClass
(
'ime-im selectable-row'
)
.
append
(
$
(
'<span>'
).
addClass
(
'ime-im-check'
),
$imeItem
);
if
(
imeSelector
.
options
.
helpHandler
)
{
$inputMethod
.
append
(
imeSelector
.
options
.
helpHandler
.
call
(
imeSelector
,
inputmethod
)
);
}
$imeList
.
append
(
$inputMethod
);
}
);
},
/**
* Create a help link element.
*
* @return {jQuery}
*/
helpLink
:
function
()
{
return
$
(
'<div>'
).
addClass
(
'ime-help-link selectable-row'
)
.
append
(
$
(
'<a>'
).
text
(
'Help'
)
.
addClass
(
'selectable-row-item'
)
.
attr
(
{
href
:
'http://github.com/wikimedia/jquery.ime'
,
target
:
'_blank'
,
'data-i18n'
:
'jquery-ime-help'
}
)
);
}
};
IMESelector
.
defaults
=
{
defaultLanguage
:
'en'
,
timeout
:
2500
// Milliseconds after which IME widget hides itself.
};
/*
* imeselector PLUGIN DEFINITION
*/
$
.
fn
.
imeselector
=
function
(
options
)
{
return
this
.
each
(
function
()
{
var
$this
=
$
(
this
),
data
=
$this
.
data
(
'imeselector'
);
if
(
!
data
)
{
$this
.
data
(
'imeselector'
,
(
data
=
new
IMESelector
(
this
,
options
)
)
);
}
if
(
typeof
options
===
'string'
)
{
data
[
options
].
call
(
$this
);
}
}
);
};
$
.
fn
.
imeselector
.
Constructor
=
IMESelector
;
selectorTemplate
=
'<div class="imeselector imeselector-toggle">'
+
'<a class="ime-name imeselector-toggle" href="#"></a>'
+
'<b class="ime-setting-caret imeselector-toggle"></b></div>'
;
MutationObserver
=
window
.
MutationObserver
||
window
.
WebKitMutationObserver
||
window
.
MozMutationObserver
;
function
isDOMAttrModifiedSupported
()
{
var
p
=
document
.
createElement
(
'p'
),
flag
=
false
;
if
(
p
.
addEventListener
)
{
p
.
addEventListener
(
'DOMAttrModified'
,
function
()
{
flag
=
true
;
},
false
);
}
else
if
(
p
.
attachEvent
)
{
p
.
attachEvent
(
'onDOMAttrModified'
,
function
()
{
flag
=
true
;
}
);
}
else
{
return
false
;
}
p
.
setAttribute
(
'id'
,
'target'
);
return
flag
;
}
$
.
fn
.
attrchange
=
function
(
callback
)
{
var
observer
;
if
(
MutationObserver
)
{
observer
=
new
MutationObserver
(
function
(
mutations
)
{
mutations
.
forEach
(
function
(
e
)
{
callback
.
call
(
e
.
target
,
e
.
attributeName
);
}
);
}
);
return
this
.
each
(
function
()
{
observer
.
observe
(
this
,
{
subtree
:
false
,
attributes
:
true
}
);
}
);
}
else
if
(
isDOMAttrModifiedSupported
()
)
{
return
this
.
on
(
'DOMAttrModified'
,
function
(
e
)
{
callback
.
call
(
this
,
e
.
originalEvent
.
attrName
);
}
);
}
else
if
(
'onpropertychange'
in
document
.
body
)
{
return
this
.
on
(
'propertychange'
,
function
()
{
callback
.
call
(
this
,
window
.
event
.
propertyName
);
}
);
}
};
}(
jQuery
)
);
(
function
(
$
)
{
'use strict'
;
$
.
extend
(
$
.
ime
.
preferences
,
{
registry
:
{
isDirty
:
false
,
language
:
null
,
previousLanguages
:
[],
// array of previous languages
previousInputMethods
:
[],
// array of previous inputmethods
imes
:
{
en
:
'system'
}
},
setLanguage
:
function
(
language
)
{
// Do nothing if there's no actual change
if
(
language
===
this
.
registry
.
language
)
{
return
;
}
this
.
registry
.
language
=
language
;
this
.
registry
.
isDirty
=
true
;
if
(
!
this
.
registry
.
previousLanguages
)
{
this
.
registry
.
previousLanguages
=
[];
}
// Add to the previous languages, but avoid duplicates.
if
(
this
.
registry
.
previousLanguages
.
indexOf
(
language
)
===
-
1
)
{
this
.
registry
.
previousLanguages
.
unshift
(
language
);
this
.
registry
.
previousLanguages
=
this
.
registry
.
previousLanguages
.
slice
(
0
,
5
);
}
},
getLanguage
:
function
()
{
return
this
.
registry
.
language
;
},
getDefaultLanguage
:
function
()
{
return
'en'
;
},
getPreviousLanguages
:
function
()
{
return
this
.
registry
.
previousLanguages
;
},
getPreviousInputMethods
:
function
()
{
return
this
.
registry
.
previousInputMethods
||
[];
},
// Set the given IM as the last used for the language
setIM
:
function
(
inputMethod
)
{
if
(
!
this
.
registry
.
imes
)
{
this
.
registry
.
imes
=
{};
}
// Do nothing if there's no actual change
if
(
inputMethod
===
this
.
registry
.
imes
[
this
.
registry
.
language
]
)
{
return
;
}
this
.
registry
.
imes
[
this
.
getLanguage
()
]
=
inputMethod
;
this
.
registry
.
isDirty
=
true
;
if
(
!
this
.
registry
.
previousInputMethods
)
{
this
.
registry
.
previousInputMethods
=
[];
}
// Add to the previous languages,
if
(
inputMethod
!==
'system'
)
{
this
.
registry
.
previousInputMethods
.
unshift
(
inputMethod
);
this
.
registry
.
previousInputMethods
=
this
.
registry
.
previousInputMethods
.
slice
(
0
,
5
);
}
},
// Return the last used or the default IM for language
getIM
:
function
(
language
)
{
if
(
!
this
.
registry
.
imes
)
{
this
.
registry
.
imes
=
{};
}
return
this
.
registry
.
imes
[
language
]
||
'system'
;
},
save
:
function
()
{
// save registry in cookies or localstorage
},
load
:
function
()
{
// load registry from cookies or localstorage
}
}
);
}(
jQuery
)
);
(
function
(
$
)
{
'use strict'
;
// All keys have quotes for consistency
/* eslint-disable quote-props */
$
.
extend
(
$
.
ime
.
sources
,
{
'ach-tilde'
:
{
name
:
'Acholi tilde'
,
source
:
'rules/ach/ach-tilde.js'
},
'af-tilde'
:
{
name
:
'Afrikaans tilde'
,
source
:
'rules/af/af-tilde.js'
},
'ajg-tilde'
:
{
name
:
'Aja tilde'
,
source
:
'rules/ajg/ajg-tilde.js'
},
'ak-qx'
:
{
name
:
'Akan QX replacement'
,
source
:
'rules/ak/ak-qx.js'
},
'ak-tilde'
:
{
name
:
'Akan tilde'
,
source
:
'rules/ak/ak-tilde.js'
},
'am-transliteration'
:
{
name
:
'ትራንስልተራትዖን'
,
source
:
'rules/am/am-transliteration.js'
},
'ann-tilde'
:
{
name
:
'Obolo tilde'
,
source
:
'rules/ann/ann-tilde.js'
},
'ar-kbd'
:
{
name
:
'لوحة المفاتيح العربية'
,
source
:
'rules/ar/ar-kbd.js'
},
'as-avro'
:
{
name
:
'অভ্ৰ'
,
source
:
'rules/as/as-avro.js'
},
'as-bornona'
:
{
name
:
'বৰ্ণনা'
,
source
:
'rules/as/as-bornona.js'
},
'as-inscript'
:
{
name
:
'ইনস্ক্ৰিপ্ট'
,
source
:
'rules/as/as-inscript.js'
},
'as-inscript2'
:
{
name
:
'ইনস্ক্ৰিপ্ট ২'
,
source
:
'rules/as/as-inscript2.js'
},
'as-phonetic'
:
{
name
:
'ফনেটিক'
,
source
:
'rules/as/as-phonetic.js'
},
'as-rodali'
:
{
name
:
'ৰ\'দালি'
,
source
:
'rules/as/as-rodali.js'
},
'as-transliteration'
:
{
name
:
'প্ৰতিৰূপান্তৰণ'
,
source
:
'rules/as/as-transliteration.js'
},
'azb-kbd'
:
{
name
:
'تۆرکجه'
,
source
:
'rules/azb/azb-kbd.js'
},
'bas-tilde'
:
{
name
:
'Ɓasaá tilde'
,
source
:
'rules/bas/bas-tilde.js'
},
'bbc-transliteration'
:
{
name
:
'Toba Transliteration'
,
source
:
'rules/bbc/bbc-transliteration.js'
},
'btm-transliteration'
:
{
name
:
'Transliteration'
,
source
:
'rules/btm/btm-transliteration.js'
},
'btm-keyboard'
:
{
name
:
'Mandailing Keyboard'
,
source
:
'rules/btm/btm-keyboard.js'
},
'bci-tilde'
:
{
name
:
'Baoulé tilde keyboard'
,
source
:
'rules/bci/bci-tilde.js'
},
'be-kbd'
:
{
name
:
'Стандартная'
,
source
:
'rules/be/be-kbd.js'
},
'be-latin'
:
{
name
:
'Łacinka'
,
source
:
'rules/be/be-latin.js'
},
'be-transliteration'
:
{
name
:
'Транслітэрацыя'
,
source
:
'rules/be/be-transliteration.js'
},
'ber-tfng'
:
{
name
:
'Tifinagh'
,
source
:
'rules/ber/ber-tfng.js'
},
'bfa-tilde'
:
{
name
:
'Bari Tilde'
,
source
:
'rules/bfa/bfa-tilde.js'
},
'bgn-kbd'
:
{
name
:
'روچ کپتین بلوچی'
,
source
:
'rules/bgn/bgn-kbd.js'
},
'bin-tilde'
:
{
name
:
'Edo tilde'
,
source
:
'rules/bin/bin-tilde.js'
},
'bkm-tilde'
:
{
name
:
'Kom tilde'
,
source
:
'rules/bkm/bkm-tilde.js'
},
'bm-alt'
:
{
name
:
'Bamanankan Alt'
,
source
:
'rules/bm/bm-alt.js'
},
'bm-tilde'
:
{
name
:
'Bamanankan tilde'
,
source
:
'rules/bm/bm-tilde.js'
},
'bn-avro'
:
{
name
:
'অভ্র'
,
source
:
'rules/bn/bn-avro.js'
},
'bn-inscript'
:
{
name
:
'ইনস্ক্ৰিপ্ট'
,
source
:
'rules/bn/bn-inscript.js'
},
'bn-inscript2'
:
{
name
:
'ইনস্ক্ৰিপ্ট ২'
,
source
:
'rules/bn/bn-inscript2.js'
},
'bn-nkb'
:
{
name
:
'জাতীয় কিবোর্ড'
,
source
:
'rules/bn/bn-nkb.js'
},
'bn-probhat'
:
{
name
:
'প্রভাত'
,
source
:
'rules/bn/bn-probhat.js'
},
'bo-ewts'
:
{
name
:
'Tibetan EWTS'
,
source
:
'rules/bo/bo-ewts.js'
},
'bo-sambhota'
:
{
name
:
'Tibetan Sambhota'
,
source
:
'rules/bo/bo-sambhota.js'
},
'bol-tilde'
:
{
name
:
'Bole - tilde'
,
source
:
'rules/bol/bol-tilde.js'
},
'bom-tilde'
:
{
name
:
'Bèrom Tilde'
,
source
:
'rules/bom/bom-tilde.js'
},
'brx-inscript'
:
{
name
:
'इनस्क्रिप्ट'
,
source
:
'rules/brx/brx-inscript.js'
},
'brx-inscript2'
:
{
name
:
'इनस्क्रिप्ट २'
,
source
:
'rules/brx/brx-inscript2.js'
},
'bwr-tilde'
:
{
name
:
'Bura tilde'
,
source
:
'rules/bwr/bwr-tilde.js'
},
'byn-geezim'
:
{
name
:
'ብሊን'
,
source
:
'rules/byn/byn-geezim.js'
},
'chn-tilde'
:
{
name
:
'Chinook wawa tilde'
,
source
:
'rules/chn/chn-tilde.js'
},
'chr'
:
{
name
:
'Cherokee Transliteration'
,
source
:
'rules/chr/chr.js'
},
'ckb-transliteration-arkbd'
:
{
name
:
'باشووری'
,
source
:
'rules/ckb/ckb-transliteration-arkbd.js'
},
'ckb-transliteration-fakbd'
:
{
name
:
'ڕۆژھەڵاتی'
,
source
:
'rules/ckb/ckb-transliteration-fakbd.js'
},
'ckb-transliteration-lakbd'
:
{
name
:
'لاتینی'
,
source
:
'rules/ckb/ckb-transliteration-lakbd.js'
},
'cv-cyr-altgr'
:
{
name
:
'Чăвашла (AltGr)'
,
source
:
'rules/cv/cv-cyr-altgr.js'
},
'cv-cyr-numbers'
:
{
name
:
'Чăвашла (цифрилисем)'
,
source
:
'rules/cv/cv-cyr-numbers.js'
},
'cv-lat-altgr'
:
{
name
:
'Căvašla (AltGr)'
,
source
:
'rules/cv/cv-lat-altgr.js'
},
'cyrl-palochka'
:
{
name
:
'Palochka'
,
source
:
'rules/cyrl/cyrl-palochka.js'
},
'da-normforms'
:
{
name
:
'Brug translitteration'
,
source
:
'rules/da/da-normforms.js'
},
'dag-alt'
:
{
name
:
'Dagbani Alt'
,
source
:
'rules/dag/dag-alt.js'
},
'dag-tilde'
:
{
name
:
'Dagbani tilde'
,
source
:
'rules/dag/dag-tilde.js'
},
'ddn-tilde'
:
{
name
:
'Dinde Tilde'
,
source
:
'rules/ddn/ddn-tilde.js'
},
'de-transliteration'
:
{
name
:
'Deutsch Tilde'
,
source
:
'rules/de/de-transliteration.js'
},
'din-fqsx'
:
{
name
:
'Dinka FQSX'
,
source
:
'rules/din/din-fqsx.js'
},
'din-tilde'
:
{
name
:
'Dinka tilde'
,
source
:
'rules/din/din-tilde.js'
},
'doi-inscript2'
:
{
name
:
'इनस्क्रिप्ट २'
,
source
:
'rules/doi/doi-inscript2.js'
},
'dua-tilde'
:
{
name
:
'Duala tilde keyboard'
,
source
:
'rules/dua/dua-tilde.js'
},
'ee-tilde'
:
{
name
:
'Ewe Tilde'
,
source
:
'rules/ee/ee-tilde.js'
},
'efi-tilde'
:
{
name
:
'Efik - tilde'
,
source
:
'rules/efi/efi-tilde.js'
},
'ekp-tilde'
:
{
name
:
'Ẹkpeye'
,
source
:
'rules/ekp/ekp-tilde.js'
},
'el-kbd'
:
{
name
:
'Τυπική πληκτρολόγιο'
,
source
:
'rules/el/el-kbd.js'
},
'eo-h'
:
{
name
:
'Esperanto h'
,
source
:
'rules/eo/eo-h.js'
},
'eo-h-f'
:
{
name
:
'Esperanto h fundamente'
,
source
:
'rules/eo/eo-h-f.js'
},
'eo-plena'
:
{
name
:
'Esperanto plena'
,
source
:
'rules/eo/eo-plena.js'
},
'eo-q'
:
{
name
:
'Esperanto q sistemo'
,
source
:
'rules/eo/eo-q.js'
},
'eo-transliteration'
:
{
name
:
'transliterigo'
,
source
:
'rules/eo/eo-transliteration.js'
},
'eo-vi'
:
{
name
:
'Esperanto vi sistemo'
,
source
:
'rules/eo/eo-vi.js'
},
'eo-x'
:
{
name
:
'Esperanto x sistemo'
,
source
:
'rules/eo/eo-x.js'
},
'fa-kbd'
:
{
name
:
'فارسی'
,
source
:
'rules/fa/fa-kbd.js'
},
'ff-alt'
:
{
name
:
'Fulfulde alt'
,
source
:
'rules/ff/ff-alt.js'
},
'ff-tilde'
:
{
name
:
'Fulfulde tilde'
,
source
:
'rules/ff/ff-tilde.js'
},
'fi-transliteration'
:
{
name
:
'translitterointi'
,
source
:
'rules/fi/fi-transliteration.js'
},
'fo-normforms'
:
{
name
:
'Føroyskt'
,
source
:
'rules/fo/fo-normforms.js'
},
'fon-tilde'
:
{
name
:
'Fon Tilde'
,
source
:
'rules/fon/fon-tilde.js'
},
'gaa-cqx'
:
{
name
:
'Ga CQX replacement'
,
source
:
'rules/gaa/gaa-cqx.js'
},
'gaa-tilde'
:
{
name
:
'Ga tilde'
,
source
:
'rules/gaa/gaa-tilde.js'
},
'gom-inscript2'
:
{
name
:
'इनस्क्रिप्ट २'
,
source
:
'rules/gom/gom-inscript2.js'
},
'got-standard'
:
{
name
:
'𐌲𐌿𐍄𐌹𐍃𐌺𐌰 𐍂𐌰𐌶𐌳𐌰'
,
source
:
'rules/got/got-standard.js'
},
'gu-inscript'
:
{
name
:
'ઇનસ્ક્રિપ્ટ'
,
source
:
'rules/gu/gu-inscript.js'
},
'gu-inscript2'
:
{
name
:
'ઇનસ્ક્રિપ્ટ ૨'
,
source
:
'rules/gu/gu-inscript2.js'
},
'gu-phonetic'
:
{
name
:
'ફોનૅટિક'
,
source
:
'rules/gu/gu-phonetic.js'
},
'gu-transliteration'
:
{
name
:
'લિપ્યંતરણ'
,
source
:
'rules/gu/gu-transliteration.js'
},
'gur-tilde'
:
{
name
:
'Farefare tilde'
,
source
:
'rules/gur/gur-tilde.js'
},
'ha-tilde'
:
{
name
:
'Hausa - tilde'
,
source
:
'rules/ha/ha-tilde.js'
},
'he-standard-2012'
:
{
name
:
'עברית עם ניקוד על בסיס אנגלית'
,
source
:
'rules/he/he-standard-2012.js'
},
'he-standard-2012-extonly'
:
{
name
:
'עברית עם ניקוד'
,
source
:
'rules/he/he-standard-2012-extonly.js'
},
'hi-bolnagri'
:
{
name
:
'बोलनागरी'
,
source
:
'rules/hi/hi-bolnagri.js'
},
'hi-inscript'
:
{
name
:
'इनस्क्रिप्ट'
,
source
:
'rules/hi/hi-inscript.js'
},
'hi-inscript2'
:
{
name
:
'इनस्क्रिप्ट २'
,
source
:
'rules/hi/hi-inscript2.js'
},
'hi-phonetic'
:
{
name
:
'फोनेटिक'
,
source
:
'rules/hi/hi-phonetic.js'
},
'hi-transliteration'
:
{
name
:
'लिप्यंतरण'
,
source
:
'rules/hi/hi-transliteration.js'
},
'hoc-transliteration'
:
{
name
:
'Ho transliteration'
,
source
:
'rules/hoc/hoc-transliteration.js'
},
'hr-kbd'
:
{
name
:
'Croatian kbd'
,
source
:
'rules/hr/hr-kbd.js'
},
'hy-emslegacy'
:
{
name
:
'Մայքրոսոֆթի հին արևելահայերեն'
,
source
:
'rules/hy/hy-emslegacy.js'
},
'hy-ephonetic'
:
{
name
:
'Հնչյունային դասավորություն'
,
source
:
'rules/hy/hy-ephonetic.js'
},
'hy-ephoneticalt'
:
{
name
:
'Հնչյունային նոր (R→Ր, F→Թ)'
,
source
:
'rules/hy/hy-ephoneticalt.js'
},
'hy-typewriter'
:
{
name
:
'Գրամեքենայի դասավորություն'
,
source
:
'rules/hy/hy-typewriter.js'
},
'hy-wmslegacy'
:
{
name
:
'Մայքրոսոֆթի հին արևմտահայերեն'
,
source
:
'rules/hy/hy-wmslegacy.js'
},
'ibb-tilde'
:
{
name
:
'Ibibio - tilde'
,
source
:
'rules/ibb/ibb-tilde.js'
},
'id-jawi'
:
{
name
:
'Jawi Keyboard'
,
source
:
'rules/id/id-jawi.js'
},
'ig-tilde'
:
{
name
:
'Igbo - tilde'
,
source
:
'rules/ig/ig-tilde.js'
},
'igl-tilde'
:
{
name
:
'Igbol - tilde'
,
source
:
'rules/igl/igl-tilde.js'
},
'ipa-sil'
:
{
name
:
'International Phonetic Alphabet - SIL'
,
source
:
'rules/fonipa/ipa-sil.js'
},
'ipa-x-sampa'
:
{
name
:
'International Phonetic Alphabet - X-SAMPA'
,
source
:
'rules/fonipa/ipa-x-sampa.js'
},
'is-normforms'
:
{
name
:
'Venjuleg eyðublöð'
,
source
:
'rules/is/is-normforms.js'
},
'ish-tilde'
:
{
name
:
'Esan Awain tilde'
,
source
:
'rules/ish/ish-tilde.js'
},
'jac-tilde'
:
{
name
:
'Jakaltek tilde'
,
source
:
'rules/jac/jac-tilde.js'
},
'jv-transliteration'
:
{
name
:
'Transliteration'
,
source
:
'rules/jv/jv-transliteration.js'
},
'jv-keyboard'
:
{
name
:
'Jawa Latin extended'
,
source
:
'rules/jv/jv-keyboard.js'
},
'ka-kbd'
:
{
name
:
'სტანდარტული კლავიატურის'
,
source
:
'rules/ka/ka-kbd.js'
},
'ka-transliteration'
:
{
name
:
'ტრანსლიტერაცია'
,
source
:
'rules/ka/ka-transliteration.js'
},
'kab-tilde'
:
{
name
:
'Taqbaylit Alatin tilde'
,
source
:
'rules/kab/kab-tilde.js'
},
'kaj-tilde'
:
{
name
:
'Jju tilde'
,
source
:
'rules/kaj/kaj-tilde.js'
},
'kbp-tilde'
:
{
name
:
'Kabɩyɛ tilde'
,
source
:
'rules/kbp/kbp-tilde.js'
},
'kcg-tilde'
:
{
name
:
'Tyap tilde'
,
source
:
'rules/kcg/kcg-tilde.js'
},
'ki-tilde'
:
{
name
:
'Gĩkũyũ'
,
source
:
'rules/ki/ki-tilde.js'
},
'kk-arabic'
:
{
name
:
'Kazakh Arabic transliteration'
,
source
:
'rules/kk/kk-arabic.js'
},
'kk-kbd'
:
{
name
:
'Кирил'
,
source
:
'rules/kk/kk-kbd.js'
},
'km-nidakyk'
:
{
name
:
'ក្តារចុចយូនីកូដខ្មែរ (NiDA)'
,
source
:
'rules/km/km-nidakyk.js'
},
'kn-inscript'
:
{
name
:
'ಇನ್ಸ್ಕ್ರಿಪ್ಟ್'
,
source
:
'rules/kn/kn-inscript.js'
},
'kn-inscript2'
:
{
name
:
'ಇನ್\u200cಸ್ಕ್ರಿಪ್ಟ್ ೨'
,
source
:
'rules/kn/kn-inscript2.js'
},
'kn-kgp'
:
{
name
:
'KGP/Nudi/KP Rao'
,
source
:
'rules/kn/kn-kgp.js'
},
'kn-transliteration'
:
{
name
:
'ಲಿಪ್ಯಂತರಣ'
,
source
:
'rules/kn/kn-transliteration.js'
},
'kr-tilde'
:
{
name
:
'Kanuri tilde'
,
source
:
'rules/kr/kr-tilde.js'
},
'kri-tilde'
:
{
name
:
'Krio tilde'
,
source
:
'rules/kri/kri-tilde.js'
},
'ky-cyrl-alt'
:
{
name
:
'Кыргыз Alt'
,
source
:
'rules/ky/ky-cyrl-alt.js'
},
'ks-inscript'
:
{
name
:
'इनस्क्रिप्ट'
,
source
:
'rules/ks/ks-inscript.js'
},
'ks-kbd'
:
{
name
:
'Kashmiri Arabic'
,
source
:
'rules/ks/ks-kbd.js'
},
'ku-h'
:
{
name
:
'Kurdî-h'
,
source
:
'rules/ku/ku-h.js'
},
'ku-tr'
:
{
name
:
'Kurdî-tr'
,
source
:
'rules/ku/ku-tr.js'
},
'kus-tilde'
:
{
name
:
'Kusaal tilde'
,
source
:
'rules/kus/kus-tilde.js'
},
'laj-tilde'
:
{
name
:
'Lango tilde'
,
source
:
'rules/laj/laj-tilde.js'
},
'lg-tilde'
:
{
name
:
'Luganda tilde'
,
source
:
'rules/lg/lg-tilde.js'
},
'ln-tilde'
:
{
name
:
'Lingála tilde'
,
source
:
'rules/ln/ln-tilde.js'
},
'lo-kbd'
:
{
name
:
'າຶກ'
,
source
:
'rules/lo/lo-kbd.js'
},
'lrc-kbd'
:
{
name
:
'لۊری شومالی'
,
source
:
'rules/lrc/lrc-kbd.js'
},
'lud-transliteration'
:
{
name
:
'lud'
,
source
:
'rules/lud/lud-transliteration.js'
},
'lut-tulalip'
:
{
name
:
'Lushootseed Tulalip'
,
source
:
'rules/lut/lut-tulalip.js'
},
'mad-tilde'
:
{
name
:
'Madhurâ tilde'
,
source
:
'rules/mad/mad-tilde.js'
},
'mai-inscript'
:
{
name
:
'इनस्क्रिप्ट'
,
source
:
'rules/mai/mai-inscript.js'
,
depends
:
'hi-inscript'
},
'mai-inscript2'
:
{
name
:
'इनस्क्रिप्ट २'
,
source
:
'rules/mai/mai-inscript2.js'
,
depends
:
'hi-inscript2'
},
'mg-tilde'
:
{
name
:
'Malagasy tilde'
,
source
:
'rules/mg/mg-tilde.js'
},
'mh'
:
{
name
:
'Kajin M̧ajeļ'
,
source
:
'rules/mh/mh.js'
},
'ml-inscript'
:
{
name
:
'ഇൻസ്ക്രിപ്റ്റ്'
,
source
:
'rules/ml/ml-inscript.js'
},
'ml-inscript2'
:
{
name
:
'ഇൻസ്ക്രിപ്റ്റ് 2'
,
source
:
'rules/ml/ml-inscript2.js'
},
'ml-transliteration'
:
{
name
:
'ലിപ്യന്തരണം'
,
source
:
'rules/ml/ml-transliteration.js'
},
'mn-cyrl'
:
{
name
:
'Кирилл'
,
source
:
'rules/mn/mn-cyrl.js'
},
'mn-todo'
:
{
name
:
'ᡐᡆᡑᡆ ᡋᡅᡔᡅᡎ᠌'
,
source
:
'rules/mn/mn-todo.js'
},
'mn-todoali'
:
{
name
:
'Todo Mongolian Ali-gali'
,
source
:
'rules/mn/mn-todoali.js'
},
'mn-trad'
:
{
name
:
'ᠮᠣᠩᠭᠣᠯ ᠪᠢᠴᠢᠭ᠌'
,
source
:
'rules/mn/mn-trad.js'
},
'mn-tradali'
:
{
name
:
'Traditional Mongolian Ali-gali'
,
source
:
'rules/mn/mn-tradali.js'
},
'mnc'
:
{
name
:
'ᠮᠠᠨᠵᡠ'
,
source
:
'rules/mnc/mnc.js'
},
'mnc-ali'
:
{
name
:
'Manchu Ali-gali'
,
source
:
'rules/mnc/mnc-ali.js'
},
'mni-inscript2'
:
{
name
:
'ইনস্ক্ৰিপ্ট ২'
,
source
:
'rules/mni/mni-inscript2.js'
},
'mnw-simplified-anonta'
:
{
name
:
'Mon Simplified Anonta'
,
source
:
'rules/mnw/mnw-simplified-anonta.js'
},
'mr-inscript'
:
{
name
:
'मराठी लिपी'
,
source
:
'rules/mr/mr-inscript.js'
},
'mr-inscript2'
:
{
name
:
'मराठी इनस्क्रिप्ट २'
,
source
:
'rules/mr/mr-inscript2.js'
},
'mr-phonetic'
:
{
name
:
'फोनेटिक'
,
source
:
'rules/mr/mr-phonetic.js'
},
'mr-transliteration'
:
{
name
:
'अक्षरांतरण'
,
source
:
'rules/mr/mr-transliteration.js'
},
'mul-bf'
:
{
name
:
'Burkina Faso tilde keyboard'
,
source
:
'rules/mul-bf/mul-bf.js'
},
'mul-click-tilde'
:
{
name
:
'Click consonants keyboard'
,
source
:
'rules/mul-click/mul-click-tilde.js'
},
'mul-cm'
:
{
name
:
'General Alphabet of Cameroon Languages tilde keyboard'
,
source
:
'rules/mul-cm/mul-cm.js'
},
'my-mm3'
:
{
name
:
'မြန်မာ၃ လက်ကွက်'
,
source
:
'rules/my/my-mm3.js'
},
'my-xkb'
:
{
name
:
'မြန်မာဘာသာ xkb'
,
source
:
'rules/my/my-xkb.js'
},
'nb-normforms'
:
{
name
:
'Normal transliterasjon'
,
source
:
'rules/nb/nb-normforms.js'
},
'nb-tildeforms'
:
{
name
:
'Tildemerket transliterasjon'
,
source
:
'rules/nb/nb-tildeforms.js'
},
'ne-inscript'
:
{
name
:
'इनस्क्रिप्ट'
,
source
:
'rules/ne/ne-inscript.js'
},
'ne-inscript2'
:
{
name
:
'इनस्क्रिप्ट २'
,
source
:
'rules/ne/ne-inscript2.js'
},
'ne-rom'
:
{
name
:
'Romanized'
,
source
:
'rules/ne/ne-rom.js'
},
'ne-trad'
:
{
name
:
'Traditional'
,
source
:
'rules/ne/ne-trad.js'
},
'ne-transliteration'
:
{
name
:
'ट्रांस्लितेरेशन'
,
source
:
'rules/ne/ne-transliteration.js'
},
'nia-tilde'
:
{
name
:
'Li Niha tilde'
,
source
:
'rules/nia/nia-tilde.js'
},
'nmz-tilde'
:
{
name
:
'Nawdm tilde'
,
source
:
'rules/nmz/nmz-tilde.js'
},
'nqo-standard-qwerty'
:
{
name
:
"N'Ko standard QWERTY"
,
source
:
'rules/nqo/nqo-standard-qwerty.js'
},
'nqo-transliteration'
:
{
name
:
"N'Ko transliteration"
,
source
:
'rules/nqo/nqo-transliteration.js'
},
'nso-tilde'
:
{
name
:
'Sesotho sa Leboa tilde'
,
source
:
'rules/nso/nso-tilde.js'
},
'nus-tilde'
:
{
name
:
'Thok Naath tilde'
,
source
:
'rules/nus/nus-tilde.js'
},
'ny-tilde'
:
{
name
:
'Chichewa / Nyanja tilde'
,
source
:
'rules/ny/ny-tilde.js'
},
'or-inscript'
:
{
name
:
'ଇନସ୍କ୍ରିପ୍ଟ'
,
source
:
'rules/or/or-inscript.js'
},
'or-inscript2'
:
{
name
:
'ଇନସ୍କ୍ରିପ୍ଟ2'
,
source
:
'rules/or/or-inscript2.js'
},
'or-lekhani'
:
{
name
:
'ଲେଖନୀ'
,
source
:
'rules/or/or-lekhani.js'
},
'or-OdiScript'
:
{
name
:
'ଓଡ଼ିସ୍କ୍ରିପ୍ଟ'
,
source
:
'rules/or/or-OdiScript.js'
},
'or-phonetic'
:
{
name
:
'ଫୋନେଟିକ'
,
source
:
'rules/or/or-phonetic.js'
},
'or-transliteration'
:
{
name
:
'ଟ୍ରାନ୍ସଲିଟରେସନ'
,
source
:
'rules/or/or-transliteration.js'
},
'pa-inscript'
:
{
name
:
'ਇਨਸਕ੍ਰਿਪਟ'
,
source
:
'rules/pa/pa-inscript.js'
},
'pa-inscript2'
:
{
name
:
'ਇਨਸਕ੍ਰਿਪਟ2'
,
source
:
'rules/pa/pa-inscript2.js'
},
'pa-jhelum'
:
{
name
:
'ਜੇਹਲਮ'
,
source
:
'rules/pa/pa-jhelum.js'
},
'pa-transliteration'
:
{
name
:
'ਲਿਪਾਂਤਰਨ'
,
source
:
'rules/pa/pa-transliteration.js'
},
'pa-phonetic'
:
{
name
:
'ਫੋਨੇਟਿਕ'
,
source
:
'rules/pa/pa-phonetic.js'
},
'phagspa'
:
{
name
:
'PhagsPa'
,
source
:
'rules/mn/phagspa.js'
},
'pms'
:
{
name
:
'Piemontèis'
,
source
:
'rules/pms/pms.js'
},
'pnt-tilde'
:
{
name
:
'Pontic tilde'
,
source
:
'rules/pnt/pnt-tilde.js'
},
'roa-tara-GVU'
:
{
name
:
'Tarandine'
,
source
:
'rules/roa-tara/roa-tara.js'
},
'ru-jcuken'
:
{
name
:
'ЙЦУКЕН'
,
source
:
'rules/ru/ru-jcuken.js'
},
'ru-kbd'
:
{
name
:
'кбд'
,
source
:
'rules/ru/ru-kbd.js'
},
'ru-phonetic'
:
{
name
:
'фонетический'
,
source
:
'rules/ru/ru-phonetic.js'
},
'ru-yawerty'
:
{
name
:
'yawerty'
,
source
:
'rules/ru/ru-yawerty.js'
},
'sa-iast'
:
{
name
:
'Romanized'
,
source
:
'rules/sa/sa-iast.js'
},
'sa-inscript'
:
{
name
:
'इनस्क्रिप्ट'
,
source
:
'rules/sa/sa-inscript.js'
},
'sa-inscript2'
:
{
name
:
'इनस्क्रिप्ट २'
,
source
:
'rules/sa/sa-inscript2.js'
},
'sa-transliteration'
:
{
name
:
'लिप्यन्तरणम्'
,
source
:
'rules/sa/sa-transliteration.js'
},
'sah-transliteration'
:
{
name
:
'Transliteration'
,
source
:
'rules/sah/sah-transliteration.js'
},
'sat-inscript2'
:
{
name
:
'इनस्क्रिप्ट २'
,
source
:
'rules/sat/sat-inscript2.js'
},
'sat-inscript2-ol-chiki'
:
{
name
:
'inscript2 ᱚᱞ ᱪᱤᱠᱤ'
,
source
:
'rules/sat/sat-inscript2-ol-chiki.js'
},
'sat-sarjom-baha'
:
{
name
:
'sarjom baha'
,
source
:
'rules/sat/sat-sarjom-baha.js'
},
'sd-inscript2'
:
{
name
:
'इनस्क्रिप्ट २'
,
source
:
'rules/sd/sd-inscript2.js'
},
'sdh-kbd'
:
{
name
:
'کوردی خوارگ'
,
source
:
'rules/sdh/sdh-kbd.js'
},
'se-normforms'
:
{
name
:
'Normal forms'
,
source
:
'rules/se/se-normforms.js'
},
'ses-tilde'
:
{
name
:
'Koyraboro Senni tilde'
,
source
:
'rules/ses/ses-tilde.js'
},
'sg-tilde'
:
{
name
:
'Sängö'
,
source
:
'rules/sg/sg-tilde.js'
},
'si-singlish'
:
{
name
:
'සිංග්ලිෂ්'
,
source
:
'rules/si/si-singlish.js'
},
'si-wijesekara'
:
{
name
:
'විජේසේකර'
,
source
:
'rules/si/si-wijesekara.js'
},
'sjo'
:
{
name
:
'ᠰᡞᠪᡝ'
,
source
:
'rules/sjo/sjo.js'
},
'sk-kbd'
:
{
name
:
'Štandardná'
,
source
:
'rules/sk/sk-kbd.js'
},
'sr-kbd'
:
{
name
:
'Стандардна'
,
source
:
'rules/sr/sr-kbd.js'
},
'st-tilde'
:
{
name
:
'Sesotho tilde'
,
source
:
'rules/st/st-tilde.js'
},
'su-keyboard'
:
{
name
:
'Sundanese keyboard'
,
source
:
'rules/su/su-keyboard.js'
},
'sv-normforms'
:
{
name
:
'Normal forms'
,
source
:
'rules/sv/sv-normforms.js'
},
'szl-tilde'
:
{
name
:
'Silesian tilde'
,
source
:
'rules/szl/szl-tilde.js'
},
'ta-99'
:
{
name
:
'தமிழ்99'
,
source
:
'rules/ta/ta-99.js'
},
'ta-bamini'
:
{
name
:
'பாமினி'
,
source
:
'rules/ta/ta-bamini.js'
},
'ta-inscript'
:
{
name
:
'இன்ஸ்கிரிப்ட்'
,
source
:
'rules/ta/ta-inscript.js'
},
'ta-inscript2'
:
{
name
:
'இன்ஸ்கிரிப்ட் 2'
,
source
:
'rules/ta/ta-inscript2.js'
},
'ta-transliteration'
:
{
name
:
'எழுத்துப்பெயர்ப்பு'
,
source
:
'rules/ta/ta-transliteration.js'
},
'te-apple'
:
{
name
:
'ఆపిల్'
,
source
:
'rules/te/te-apple.js'
},
'te-inscript'
:
{
name
:
'ఇన్\u200dస్క్రిప్ట్'
,
source
:
'rules/te/te-inscript.js'
},
'te-inscript2'
:
{
name
:
'ఇన్\u200dస్క్రిప్ట్ 2'
,
source
:
'rules/te/te-inscript2.js'
},
'te-modular'
:
{
name
:
'మాడ్యులర్'
,
source
:
'rules/te/te-modular.js'
},
'te-transliteration'
:
{
name
:
'లిప్యంతరీకరణ'
,
source
:
'rules/te/te-transliteration.js'
},
'th-kedmanee'
:
{
name
:
'เกษมณี'
,
source
:
'rules/th/th-kedmanee.js'
},
'th-pattachote'
:
{
name
:
'ปัตตะโชติ'
,
source
:
'rules/th/th-pattachote.js'
},
'ti-geezim'
:
{
name
:
'ትግርኛ'
,
source
:
'rules/ti/ti-geezim.js'
},
'tig-geezim'
:
{
name
:
'Tigre GeezIM'
,
source
:
'rules/tig/tig-geezim.js'
},
'tn-tilde'
:
{
name
:
'Setswana tilde'
,
source
:
'rules/tn/tn-tilde.js'
},
'tum-tilde'
:
{
name
:
'ChiTumbuka tilde'
,
source
:
'rules/tum/tum-tilde.js'
},
'udm-alt'
:
{
name
:
'Удмурт ALT'
,
source
:
'rules/udm/udm-alt.js'
},
'ug-kbd'
:
{
name
:
'Uyghur kbd'
,
source
:
'rules/ug/ug-kbd.js'
},
'uk-kbd'
:
{
name
:
'кбд'
,
source
:
'rules/uk/uk-kbd.js'
},
'ur-phonetic'
:
{
name
:
'صوتی'
,
source
:
'rules/ur/ur-phonetic.js'
},
'ur-transliteration'
:
{
name
:
'ٹرانسلٹریشن'
,
source
:
'rules/ur/ur-transliteration.js'
},
'uz-kbd'
:
{
name
:
'Uzbek kbd'
,
source
:
'rules/uz/uz-kbd.js'
},
've-tilde'
:
{
name
:
'TshiVenḓa tilde'
,
source
:
'rules/ve/ve-tilde.js'
},
'vai-transliteration'
:
{
name
:
'Vai transliteration'
,
source
:
'rules/vai/vai-transliteration.js'
},
'vec-GVU'
:
{
name
:
'Vèneto'
,
source
:
'rules/vec/vec-GVU.js'
},
'wlx-tilde'
:
{
name
:
'Waale tilde'
,
source
:
'rules/wlx/wlx-tilde.js'
},
'wo-alt'
:
{
name
:
'Wolof Alt'
,
source
:
'rules/wo/wo-alt.js'
},
'wo-tilde'
:
{
name
:
'Wolof tilde'
,
source
:
'rules/wo/wo-tilde.js'
},
'yo-alt'
:
{
name
:
'Yorùbá Alt'
,
source
:
'rules/yo/yo-alt.js'
},
'yo-tilde'
:
{
name
:
'Yorùbá tilde'
,
source
:
'rules/yo/yo-tilde.js'
},
'zh-pinyin-transliteration'
:
{
name
:
'拼音符号输入法'
,
source
:
'rules/zh/zh-pinyin-transliteration.js'
}
}
);
/* eslint-disable quote-props */
$
.
extend
(
$
.
ime
.
languages
,
{
abr
:
{
autonym
:
'Abron'
,
inputmethods
:
[
'ak-qx'
,
'ak-tilde'
]
},
ach
:
{
autonym
:
'Acoli'
,
inputmethods
:
[
'ach-tilde'
]
},
ady
:
{
autonym
:
'адыгэбзэ'
,
inputmethods
:
[
'cyrl-palochka'
]
},
af
:
{
autonym
:
'Afrikaans'
,
inputmethods
:
[
'af-tilde'
]
},
ahr
:
{
autonym
:
'अहिराणी'
,
inputmethods
:
[
'mr-transliteration'
,
'mr-inscript'
]
},
ajg
:
{
autonym
:
'ajagbe'
,
inputmethods
:
[
'ajg-tilde'
]
},
am
:
{
autonym
:
'አማርኛ'
,
inputmethods
:
[
'am-transliteration'
]
},
ann
:
{
autonym
:
'Obolo'
,
inputmethods
:
[
'ann-tilde'
]
},
ar
:
{
autonym
:
'العربية'
,
inputmethods
:
[
'ar-kbd'
]
},
as
:
{
autonym
:
'অসমীয়া'
,
inputmethods
:
[
'as-transliteration'
,
'as-avro'
,
'as-bornona'
,
'as-inscript'
,
'as-phonetic'
,
'as-inscript2'
,
'as-rodali'
]
},
av
:
{
autonym
:
'авар'
,
inputmethods
:
[
'cyrl-palochka'
]
},
azb
:
{
autonym
:
'تۆرکجه'
,
inputmethods
:
[
'azb-kbd'
]
},
bas
:
{
autonym
:
'ɓasaá'
,
inputmethods
:
[
'bas-tilde'
,
'mul-cm'
]
},
bbc
:
{
autonym
:
'Batak Toba'
,
inputmethods
:
[
'bbc-transliteration'
]
},
btm
:
{
autonym
:
'Batak Mandailing'
,
inputmethods
:
[
'btm-keyboard'
,
'btm-transliteration'
]
},
bci
:
{
autonym
:
'wawle'
,
inputmethods
:
[
'bci-tilde'
]
},
be
:
{
autonym
:
'беларуская'
,
inputmethods
:
[
'be-transliteration'
,
'be-latin'
,
'be-kbd'
]
},
'be-tarask'
:
{
autonym
:
'беларуская (тарашкевіца)'
,
inputmethods
:
[
'be-transliteration'
,
'be-latin'
]
},
bfa
:
{
autonym
:
'Bari'
,
inputmethods
:
[
'bfa-tilde'
]
},
bh
:
{
autonym
:
'भोजपुरी'
,
inputmethods
:
[
'hi-transliteration'
]
},
bgn
:
{
autonym
:
'روچ کپتین بلوچی'
,
inputmethods
:
[
'bgn-kbd'
]
},
bin
:
{
autonym
:
'Ẹdo'
,
inputmethods
:
[
'bin-tilde'
]
},
bho
:
{
autonym
:
'भोजपुरी'
,
inputmethods
:
[
'hi-transliteration'
]
},
bkm
:
{
autonym
:
'Itaŋikom'
,
inputmethods
:
[
'bkm-tilde'
,
'mul-cm'
]
},
bm
:
{
autonym
:
'Bamanankan'
,
inputmethods
:
[
'bm-alt'
,
'bm-tilde'
]
},
bn
:
{
autonym
:
'বাংলা'
,
inputmethods
:
[
'bn-avro'
,
'bn-inscript'
,
'bn-nkb'
,
'bn-probhat'
,
'bn-inscript2'
]
},
bo
:
{
autonym
:
'བོད་ཡིག།'
,
inputmethods
:
[
'bo-ewts'
,
'bo-sambhota'
]
},
bol
:
{
autonym
:
'bòo pìkkà'
,
inputmethods
:
[
'bol-tilde'
]
},
bom
:
{
autonym
:
'bèrom'
,
inputmethods
:
[
'bom-tilde'
]
},
brx
:
{
autonym
:
'बोड़ो'
,
inputmethods
:
[
'brx-inscript'
,
'brx-inscript2'
]
},
bum
:
{
autonym
:
'bulu'
,
inputmethods
:
[
'mul-cm'
]
},
bwr
:
{
autonym
:
'bura'
,
inputmethods
:
[
'bwr-tilde'
]
},
byn
:
{
autonym
:
'ብሊን'
,
inputmethods
:
[
'byn-geezim'
]
},
ce
:
{
autonym
:
'нохчийн'
,
inputmethods
:
[
'cyrl-palochka'
]
},
chn
:
{
autonym
:
'chinook wawa'
,
inputmethods
:
[
'chn-tilde'
]
},
chr
:
{
autonym
:
'ᏣᎳᎩ'
,
inputmethods
:
[
'chr'
]
},
ckb
:
{
autonym
:
'کوردی'
,
inputmethods
:
[
'ckb-transliteration-arkbd'
,
'ckb-transliteration-fakbd'
,
'ckb-transliteration-lakbd'
]
},
cv
:
{
autonym
:
'Чăвашла'
,
inputmethods
:
[
'cv-cyr-altgr'
,
'cv-lat-altgr'
,
'cv-cyr-numbers'
]
},
da
:
{
autonym
:
'Dansk'
,
inputmethods
:
[
'da-normforms'
]
},
dag
:
{
autonym
:
'Dagbani'
,
inputmethods
:
[
'dag-alt'
,
'dag-tilde'
]
},
dar
:
{
autonym
:
'дарган'
,
inputmethods
:
[
'cyrl-palochka'
]
},
ddn
:
{
autonym
:
'dendi'
,
inputmethods
:
[
'ddn-tilde'
]
},
de
:
{
autonym
:
'Deutsch'
,
inputmethods
:
[
'de-transliteration'
]
},
dga
:
{
autonym
:
'Dagaare'
,
inputmethods
:
[
'mul-bf'
]
},
din
:
{
autonym
:
'Thuɔŋjäŋ'
,
inputmethods
:
[
'din-fqsx'
,
'din-tilde'
]
},
diq
:
{
autonym
:
'Kirdkî'
,
inputmethods
:
[
'ku-h'
,
'ku-tr'
]
},
doi
:
{
autonym
:
'डोगरी'
,
inputmethods
:
[
'doi-inscript2'
]
},
dua
:
{
autonym
:
'Duálá'
,
inputmethods
:
[
'dua-tilde'
]
},
en
:
{
autonym
:
'English'
,
inputmethods
:
[
'ipa-sil'
,
'ipa-x-sampa'
]
},
ee
:
{
autonym
:
'Èʋegbe'
,
inputmethods
:
[
'ee-tilde'
]
},
efi
:
{
autonym
:
'efịk'
,
inputmethods
:
[
'efi-tilde'
]
},
ekp
:
{
autonym
:
'ẹkpeye'
,
inputmethods
:
[
'ekp-tilde'
]
},
el
:
{
autonym
:
'Ελληνικά'
,
inputmethods
:
[
'el-kbd'
]
},
eo
:
{
autonym
:
'Esperanto'
,
inputmethods
:
[
'eo-transliteration'
,
'eo-h'
,
'eo-h-f'
,
'eo-plena'
,
'eo-q'
,
'eo-vi'
,
'eo-x'
]
},
fa
:
{
autonym
:
'فارسی'
,
inputmethods
:
[
'fa-kbd'
]
},
fat
:
{
autonym
:
'mfantse'
,
inputmethods
:
[
'ak-qx'
,
'ak-tilde'
]
},
ff
:
{
autonym
:
'Fulfulde'
,
inputmethods
:
[
'ff-alt'
,
'ff-tilde'
]
},
fi
:
{
autonym
:
'Suomi'
,
inputmethods
:
[
'fi-transliteration'
]
},
fo
:
{
autonym
:
'Føroyskt'
,
inputmethods
:
[
'fo-normforms'
]
},
fon
:
{
autonym
:
'Fon'
,
inputmethods
:
[
'fon-tilde'
]
},
fonipa
:
{
autonym
:
'International Phonetic Alphabet'
,
inputmethods
:
[
'ipa-sil'
,
'ipa-x-sampa'
]
},
gaa
:
{
autonym
:
'Ga'
,
inputmethods
:
[
'gaa-cqx'
,
'gaa-tilde'
]
},
got
:
{
autonym
:
'𐌲𐌿𐍄𐌹𐍃𐌺𐌰 𐍂𐌰𐌶𐌳𐌰'
,
inputmethods
:
[
'got-standard'
]
},
ha
:
{
autonym
:
'Hausa'
,
inputmethods
:
[
'ha-tilde'
]
},
ibb
:
{
autonym
:
'ibibio'
,
inputmethods
:
[
'ibb-tilde'
]
},
id
:
{
autonym
:
'Jawi'
,
inputmethods
:
[
'id-jawi'
]
},
ig
:
{
autonym
:
'Igbo'
,
inputmethods
:
[
'ig-tilde'
]
},
igl
:
{
autonym
:
'Igala'
,
inputmethods
:
[
'igl-tilde'
]
},
gom
:
{
autonym
:
'गोंयची कोंकणी / Gõychi Konknni'
,
inputmethods
:
[
'hi-transliteration'
,
'hi-inscript'
,
'gom-inscript2'
]
},
gu
:
{
autonym
:
'ગુજરાતી'
,
inputmethods
:
[
'gu-transliteration'
,
'gu-inscript'
,
'gu-inscript2'
,
'gu-phonetic'
]
},
gur
:
{
autonym
:
'farefare'
,
inputmethods
:
[
'gur-tilde'
]
},
he
:
{
autonym
:
'עברית'
,
inputmethods
:
[
'he-standard-2012-extonly'
,
'he-standard-2012'
]
},
hi
:
{
autonym
:
'हिन्दी'
,
inputmethods
:
[
'hi-transliteration'
,
'hi-inscript'
,
'hi-bolnagri'
,
'hi-phonetic'
,
'hi-inscript2'
]
},
hne
:
{
autonym
:
'छत्तीसगढ़ी'
,
inputmethods
:
[
'hi-transliteration'
]
},
hoc
:
{
autonym
:
'𑢹𑣉𑣉'
,
inputmethods
:
[
'hoc-transliteration'
]
},
hr
:
{
autonym
:
'Hrvatski'
,
inputmethods
:
[
'hr-kbd'
]
},
hy
:
{
autonym
:
'հայերեն'
,
inputmethods
:
[
'hy-ephonetic'
,
'hy-typewriter'
,
'hy-ephoneticalt'
,
'hy-emslegacy'
,
'hy-wmslegacy'
]
},
inh
:
{
autonym
:
'гӀалгӀай'
,
inputmethods
:
[
'cyrl-palochka'
]
},
is
:
{
autonym
:
'Íslenska'
,
inputmethods
:
[
'is-normforms'
]
},
ish
:
{
autonym
:
'awain'
,
inputmethods
:
[
'ish-tilde'
]
},
jac
:
{
autonym
:
'Abꞌxubꞌal Poptiꞌ'
,
inputmethods
:
[
'jac-tilde'
]
},
jv
:
{
autonym
:
'ꦧꦱꦗꦮ (Basa Jawa)'
,
inputmethods
:
[
'jv-transliteration'
,
'jv-keyboard'
]
},
ka
:
{
autonym
:
'ქართული ენა'
,
inputmethods
:
[
'ka-transliteration'
,
'ka-kbd'
]
},
kab
:
{
autonym
:
'Taqbaylit / ⵜⴰⵇⴱⴰⵢⵍⵉⵜ'
,
inputmethods
:
[
'kab-tilde'
,
'ber-tfng'
]
},
kaj
:
{
autonym
:
'Jju'
,
inputmethods
:
[
'kaj-tilde'
]
},
kbd
:
{
autonym
:
'адыгэбзэ (къэбэрдеибзэ)'
,
inputmethods
:
[
'cyrl-palochka'
]
},
kbp
:
{
autonym
:
'Kabɩyɛ'
,
inputmethods
:
[
'kbp-tilde'
]
},
kcg
:
{
autonym
:
'Tyap'
,
inputmethods
:
[
'kcg-tilde'
]
},
ken
:
{
autonym
:
'kɛ́nyáŋ'
,
inputmethods
:
[
'mul-cm'
]
},
ki
:
{
autonym
:
'Gĩkũyũ'
,
inputmethods
:
[
'ki-tilde'
]
},
kk
:
{
autonym
:
'Қазақша'
,
inputmethods
:
[
'kk-kbd'
,
'kk-arabic'
]
},
km
:
{
autonym
:
'ភាសាខ្មែរ'
,
inputmethods
:
[
'km-nidakyk'
]
},
kn
:
{
autonym
:
'ಕನ್ನಡ'
,
inputmethods
:
[
'kn-transliteration'
,
'kn-inscript'
,
'kn-kgp'
,
'kn-inscript2'
]
},
kr
:
{
autonym
:
'kanuri'
,
inputmethods
:
[
'kr-tilde'
]
},
kri
:
{
autonym
:
'Krio'
,
inputmethods
:
[
'kri-tilde'
]
},
ks
:
{
autonym
:
'कॉशुर / کٲشُر'
,
inputmethods
:
[
'ks-inscript'
,
'ks-kbd'
]
},
ky
:
{
autonym
:
'Кыргыз'
,
inputmethods
:
[
'ky-cyrl-alt'
]
},
ku
:
{
autonym
:
'Kurdî'
,
inputmethods
:
[
'ku-h'
,
'ku-tr'
]
},
kus
:
{
autonym
:
'Kʋsaal'
,
inputmethods
:
[
'kus-tilde'
]
},
laj
:
{
autonym
:
'Lëblaŋo'
,
inputmethods
:
[
'laj-tilde'
]
},
lbe
:
{
autonym
:
'лакку'
,
inputmethods
:
[
'cyrl-palochka'
]
},
lez
:
{
autonym
:
'лезги'
,
inputmethods
:
[
'cyrl-palochka'
]
},
lg
:
{
autonym
:
'Luganda'
,
inputmethods
:
[
'lg-tilde'
]
},
ln
:
{
autonym
:
'Lingála'
,
inputmethods
:
[
'ln-tilde'
]
},
lo
:
{
autonym
:
'ລາວ'
,
inputmethods
:
[
'lo-kbd'
]
},
lrc
:
{
autonym
:
'لۊری شومالی'
,
inputmethods
:
[
'lrc-kbd'
]
},
lud
:
{
autonym
:
'lüüdi'
,
inputmethods
:
[
'lud-transliteration'
]
},
lut
:
{
autonym
:
'dxʷləšucid'
,
inputmethods
:
[
'lut-tulalip'
]
},
mai
:
{
autonym
:
'मैथिली'
,
inputmethods
:
[
'mai-inscript'
,
'mai-inscript2'
]
},
mad
:
{
autonym
:
'madhurâ'
,
inputmethods
:
[
'mad-tilde'
]
},
mg
:
{
autonym
:
'Malagasy'
,
inputmethods
:
[
'mg-tilde'
]
},
mh
:
{
autonym
:
'Kajin M̧ajeļ'
,
inputmethods
:
[
'mh'
]
},
ml
:
{
autonym
:
'മലയാളം'
,
inputmethods
:
[
'ml-transliteration'
,
'ml-inscript'
,
'ml-inscript2'
]
},
mn
:
{
autonym
:
'Монгол'
,
inputmethods
:
[
'mn-cyrl'
,
'mn-trad'
,
'mn-todo'
,
'mn-tradali'
,
'mn-todoali'
,
'phagspa'
]
},
mnc
:
{
autonym
:
'ᠮᠠᠨᠵᡠ'
,
inputmethods
:
[
'mnc'
,
'mnc-ali'
]
},
mni
:
{
autonym
:
'Manipuri'
,
inputmethods
:
[
'mni-inscript2'
]
},
mnw
:
{
autonym
:
'ဘာသာမန်'
,
inputmethods
:
[
'mnw-simplified-anonta'
]
},
mos
:
{
autonym
:
'moore'
,
inputmethods
:
[
'mul-bf'
]
},
mr
:
{
autonym
:
'मराठी'
,
inputmethods
:
[
'mr-transliteration'
,
'mr-inscript2'
,
'mr-inscript'
,
'mr-phonetic'
]
},
my
:
{
autonym
:
'မြန်မာ'
,
inputmethods
:
[
'my-mm3'
,
'my-xkb'
]
},
naq
:
{
autonym
:
'Khoekhoegowab'
,
inputmethods
:
[
'mul-click-tilde'
]
},
nb
:
{
autonym
:
'Norsk (bokmål)'
,
inputmethods
:
[
'nb-normforms'
,
'nb-tildeforms'
]
},
ne
:
{
autonym
:
'नेपाली'
,
inputmethods
:
[
'ne-transliteration'
,
'ne-inscript2'
,
'ne-inscript'
,
'ne-rom'
,
'ne-trad'
]
},
'new'
:
{
autonym
:
'नेपाल भाषा'
,
inputmethods
:
[
'hi-transliteration'
,
'hi-inscript'
]
},
nia
:
{
autonym
:
'li niha'
,
inputmethods
:
[
'nia-tilde'
]
},
nmz
:
{
autonym
:
'nawdm'
,
inputmethods
:
[
'nmz-tilde'
]
},
nn
:
{
autonym
:
'Norsk (nynorsk)'
,
inputmethods
:
[
'nb-normforms'
,
'nb-tildeforms'
]
},
nnh
:
{
autonym
:
'ngiembɔɔn'
,
inputmethods
:
[
'mul-cm'
]
},
nqo
:
{
autonym
:
'ߒߞߏ'
,
inputmethods
:
[
'nqo-standard-qwerty'
,
'nqo-transliteration'
]
},
nso
:
{
autonym
:
'Sesotho sa Leboa'
,
inputmethods
:
[
'nso-tilde'
]
},
nus
:
{
autonym
:
'Thok Naath'
,
inputmethods
:
[
'nus-tilde'
]
},
ny
:
{
autonym
:
'Chichewa'
,
inputmethods
:
[
'ny-tilde'
]
},
nzi
:
{
autonym
:
'Nzema'
,
inputmethods
:
[
'ak-tilde'
]
},
or
:
{
autonym
:
'ଓଡ଼ିଆ'
,
inputmethods
:
[
'or-phonetic'
,
'or-transliteration'
,
'or-inscript'
,
'or-inscript2'
,
'or-lekhani'
,
'or-OdiScript'
]
},
pa
:
{
autonym
:
'ਪੰਜਾਬੀ'
,
inputmethods
:
[
'pa-transliteration'
,
'pa-inscript'
,
'pa-phonetic'
,
'pa-inscript2'
,
'pa-jhelum'
]
},
pms
:
{
autonym
:
'Piemontèis'
,
inputmethods
:
[
'pms'
]
},
pnt
:
{
autonym
:
'Ποντιακά'
,
inputmethods
:
[
'pnt-tilde'
]
},
rif
:
{
autonym
:
'ⵜⴰⵔⵉⴼⵉⵜ'
,
inputmethods
:
[
'ber-tfng'
]
},
'roa-tara'
:
{
autonym
:
'Tarandine'
,
inputmethods
:
[
'roa-tara-GVU'
]
},
ru
:
{
autonym
:
'русский'
,
inputmethods
:
[
'ru-jcuken'
,
'ru-kbd'
,
'ru-phonetic'
,
'ru-yawerty'
]
},
sa
:
{
autonym
:
'संस्कृत'
,
inputmethods
:
[
'sa-transliteration'
,
'sa-inscript2'
,
'sa-inscript'
,
'sa-iast'
]
},
sah
:
{
autonym
:
'саха тыла'
,
inputmethods
:
[
'sah-transliteration'
]
},
sat
:
{
autonym
:
'ᱥᱟᱱᱛᱟᱞᱤ (संताली)'
,
inputmethods
:
[
'sat-sarjom-baha'
,
'sat-inscript2-ol-chiki'
,
'sat-inscript2'
]
},
sd
:
{
autonym
:
'सिंधी'
,
inputmethods
:
[
'sd-inscript2'
]
},
sdh
:
{
autonym
:
'کوردی خوارگ'
,
inputmethods
:
[
'sdh-kbd'
]
},
se
:
{
autonym
:
'Davvisámegiella'
,
inputmethods
:
[
'se-normforms'
]
},
ses
:
{
autonym
:
'Koyraboro Senni'
,
inputmethods
:
[
'ses-tilde'
]
},
sg
:
{
autonym
:
'Sängö'
,
inputmethods
:
[
'sg-tilde'
]
},
shi
:
{
autonym
:
'ⵜⴰⵛⵍⵃⵉⵜ'
,
inputmethods
:
[
'ber-tfng'
]
},
si
:
{
autonym
:
'සිංහල'
,
inputmethods
:
[
'si-singlish'
,
'si-wijesekara'
]
},
sjo
:
{
autonym
:
'ᠰᡞᠪᡝ'
,
inputmethods
:
[
'sjo'
]
},
sk
:
{
autonym
:
'Slovenčina'
,
inputmethods
:
[
'sk-kbd'
]
},
sr
:
{
autonym
:
'Српски / srpski'
,
inputmethods
:
[
'sr-kbd'
]
},
st
:
{
autonym
:
'Sesotho'
,
inputmethods
:
[
'st-tilde'
]
},
su
:
{
autonym
:
'Sunda'
,
inputmethods
:
[
'su-keyboard'
]
},
sv
:
{
autonym
:
'Svenska'
,
inputmethods
:
[
'sv-normforms'
]
},
szl
:
{
autonym
:
'Ślůnski'
,
inputmethods
:
[
'szl-tilde'
]
},
ta
:
{
autonym
:
'தமிழ்'
,
inputmethods
:
[
'ta-transliteration'
,
'ta-99'
,
'ta-inscript'
,
'ta-bamini'
,
'ta-inscript2'
]
},
tcy
:
{
autonym
:
'ತುಳು'
,
inputmethods
:
[
'kn-transliteration'
,
'kn-inscript'
,
'kn-kgp'
,
'kn-inscript2'
]
},
te
:
{
autonym
:
'తెలుగు'
,
inputmethods
:
[
'te-transliteration'
,
'te-inscript'
,
'te-inscript2'
,
'te-apple'
,
'te-modular'
]
},
th
:
{
autonym
:
'ไทย'
,
inputmethods
:
[
'th-kedmanee'
,
'th-pattachote'
]
},
ti
:
{
autonym
:
'ትግርኛ'
,
inputmethods
:
[
'ti-geezim'
]
},
tig
:
{
autonym
:
'ትግሬ'
,
inputmethods
:
[
'tig-geezim'
]
},
tkr
:
{
autonym
:
'цӀаӀхна миз'
,
inputmethods
:
[
'cyrl-palochka'
]
},
tn
:
{
autonym
:
'Setswana'
,
inputmethods
:
[
'tn-tilde'
]
},
tum
:
{
autonym
:
'ChiTumbuka'
,
inputmethods
:
[
'tum-tilde'
]
},
tw
:
{
autonym
:
'Twi'
,
inputmethods
:
[
'ak-qx'
,
'ak-tilde'
]
},
tzm
:
{
autonym
:
'ⵜⴰⵎⴰⵣⵉⵖⵜ'
,
inputmethods
:
[
'ber-tfng'
]
},
udm
:
{
autonym
:
'удмурт'
,
inputmethods
:
[
'udm-alt'
]
},
uk
:
{
autonym
:
'Українська'
,
inputmethods
:
[
'uk-kbd'
]
},
ug
:
{
autonym
:
'ئۇيغۇرچە / Uyghurche'
,
inputmethods
:
[
'ug-kbd'
]
},
ur
:
{
autonym
:
'اردو'
,
inputmethods
:
[
'ur-transliteration'
,
'ur-phonetic'
]
},
uz
:
{
autonym
:
'Oʻzbekcha'
,
inputmethods
:
[
'uz-kbd'
]
},
vai
:
{
autonym
:
'ꕙꔤ'
,
inputmethods
:
[
'vai-transliteration'
]
},
ve
:
{
autonym
:
'TshiVenḓa'
,
inputmethods
:
[
've-tilde'
]
},
vec
:
{
autonym
:
'Vèneto'
,
inputmethods
:
[
'vec-GVU'
]
},
wlx
:
{
autonym
:
'Waale'
,
inputmethods
:
[
'wlx-tilde'
]
},
wo
:
{
autonym
:
'Wolof'
,
inputmethods
:
[
'wo-alt'
,
'wo-tilde'
]
},
yo
:
{
autonym
:
'Yorùbá'
,
inputmethods
:
[
'yo-alt'
,
'yo-tilde'
]
},
zh
:
{
autonym
:
'中文'
,
inputmethods
:
[
'zh-pinyin-transliteration'
]
}
}
);
}(
jQuery
)
);
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sat, Oct 3, 13:11 (2 d, 1 h ago)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
70/41/7f9e95baaa480153e0ad5dac55d6
Default Alt Text
jquery.ime.js (81 KB)
Attached To
Mode
rMWPROD MediaWiki Production
Attached
Detach File
Event Timeline
Log In to Comment