Skip to content
WM KeyboardWM Keyboard
Accessibility

Importing from other keyboards

Bring layouts, themes, dictionaries, input methods and whole settings backups over from FlorisBoard, HeliBoard, LeanType, FUTO, CleverKeys, Unexpected Keyboard, AnySoftKeyboard, Samsung Keyboard (Keys Cafe), Multiling O, Gboard, gcin, OpenVanilla, Rime and m17n, plus layouts made for Windows, macOS and Linux: what converts, what doesn't, and why.

Switching keyboards usually means leaving your layouts, themes and dictionaries behind. WM Keyboard reads FlorisBoard, HeliBoard, LeanType, FUTO, Unexpected Keyboard, CleverKeys, Samsung Keyboard (Keys Cafe) and Multiling O files directly and converts them into its own, so the grid you built, the theme you picked and the word list you collected come with you. It also reads the layout files people make for computers (Windows .klc, macOS .keylayout and Linux XKB), which is where a lot of layouts for smaller languages live.

Conversion is honest about being lossy. A layout import always ends on a confirm dialog that lists what changed and what could not be carried, and nothing is written until you accept it. A .flex theme opened from a file manager gets the same treatment. The FlorisBoard button inside Settings is the one route without a confirm step: it saves the theme straight away and then tells you what it saved. Saved is not switched on, so you still get to look first.

FileFromOpens as
.json layoutFlorisBoard, HeliBoardA custom layout
.txt layoutHeliBoardA custom layout
.yaml layoutFUTO KeyboardA custom layout
.kcf layoutSamsung Keyboard, shared from Keys CafeA custom layout, kept exactly as it was laid out
DIY or DIY+ layout text, or a settings exportMultiling O KeyboardA custom layout with its symbols and AltGr pages, or every layout in the export
.xml layoutUnexpected Keyboard, CleverKeysA custom layout that keeps the swipes to each key’s corners
.klc layoutWindows, made in Microsoft Keyboard Layout CreatorA custom layout, with AltGr and dead-key letters on press and hold
.keylayout layoutmacOS, made in UkeleleA custom layout, with Option and dead-key letters on press and hold
XKB symbols fileLinuxA custom layout for each variant in the file
.flex themeFlorisBoard 0.4 and laterOne theme, one look per theme in the file
.zip themeFUTO KeyboardOne theme, with its background picture and font
.flex language packFlorisBoardA Cangjie or stroke table for Chinese
.cin tablegcin, hime, OpenVanilla, xcin, and the shared Cangjie, Array, Boshiamy, Dayi and Wubi tablesA layout that types the table: see Input methods
.schema.yaml with its .dict.yaml filesRime (Weasel, Squirrel, Trime, fcitx5-rime)A layout that types the schema
.mimm17n (ibus-m17n, fcitx5-m17n): ITRANS, InScript, Tamil99 and the other Indic methodsA layout whose rules write the text as you type
Colour theme textHeliBoard, LeanTypeOne theme, from a file or from the clipboard
OK_Settings_Begin theme text or a theme linkMultiling O KeyboardOne theme, from a file or from the clipboard
.zip themeGboard, the Rboard communityOne theme, with a look each for key borders on and off
.zip or .pack theme packRboardAny or all of the themes inside, each its own theme
.keyman-touch-layoutKeymanA custom layout, without the keyboard’s rules
.kmp packageKeymanA custom layout and its typing rules
.combined word listHeliBoard, LeanType, FUTO, any AOSP keyboardA custom dictionary
.dict dictionaryHeliBoard, LeanType, FUTO, OpenBoard, GAppsA custom dictionary
PersonalDictionary.zip, or the dictionary.txt inside itGboardWords in your personal dictionary, and shortcuts as snippets: see Gboard’s personal dictionary
Backup .zipHeliBoard, LeanType, FlorisBoard, CleverKeysA list of everything inside to pick from: see Whole backups
Backup .backupFUTO KeyboardThe same list
AnySoftKeyboardPrefs.xml, or a CleverKeys settings .jsonAnySoftKeyboard, CleverKeysThe same list, settings only

HeliBoard’s JSON layouts use FlorisBoard’s format, so one reader handles both. LeanType is a HeliBoard fork, so its layouts and themes are HeliBoard’s.

Keyman is a different case. 862 Keyman key grids are already built into the app, so for most of them there’s nothing to import. You can still open a .keyman-touch-layout file or a full .kmp package yourself, which is how you’d add a keyboard that isn’t bundled or one you’re writing. A .kmp brings its typing rules with it; a touch layout file does not. See Keyman layouts.

Most keyboards can save everything to one file: their settings, your layouts, your themes and the words they learned. WM Keyboard reads that file whole and shows you what is in it, one row per item, before anything is written. Every row starts ticked. Untick what you don’t want, then tap Import.

Open the file from WM Keyboard  Data  Backup & restore  Import from another keyboard, from a file manager, or from Restore a backup on the first page of the setup wizard, where it also skips the rest of the wizard.

To make the file on the other keyboard:

KeyboardWhat to look for
HeliBoard, LeanTypeBackup and restore in its settings, under Advanced. You get a .zip
FUTO KeyboardExport settings in its settings. You get a .backup file, which is a ZIP
FlorisBoardBackup & Restore in its settings, under Advanced. You get a .zip
CleverKeysIts backup screen. A full backup .zip or a settings .json both work
AnySoftKeyboardIts backup screen. You get AnySoftKeyboardPrefs.xml

Menu names differ between versions of each keyboard; look for “backup” or “export” in its settings.

PartHeliBoard, LeanTypeFUTOFlorisBoardCleverKeys, AnySoftKeyboard
Your own letter layoutsYesYesYesCleverKeys: yes, with the language you set for each. AnySoftKeyboard: no
Your colour themesYes, and the one in use is switched onYes, and the one in use is switched onYes, and the one in use is switched onNo
Your languagesYes, each with the closest built-in layout, or with your own layout when it is imported tooYesYesNo
Dictionaries you addedYesYesNone in the backupNo
Words learned from your typingYes, as a word listYes, as a word listNone in the backupNo
Words you added by handNone in the backup, see the note belowYes, as words you added hereNone in the backupNo
Words never suggestedYesYesNoNo
SettingsYesYesYesYes

Languages are added in front of the ones you already have, and the first becomes the one you type in. The app downloads each new language’s word list and prediction data in the background, the same way the setup wizard does.

A layout keeps its name. HeliBoard stores the name it was given in its file name, and that is what you see. A layout made for one language is filed under that language; a layout made for a whole script (HeliBoard’s “Latin” layouts) is filed under the language its letters suggest. You can change it later in the layout editor.

Learned words arrive as their own list under Custom dictionaries, not mixed into this keyboard’s learning, so you can switch them off or delete them in one place.

Only settings that mean exactly the same thing in both keyboards are offered. Each one is a row of its own, with the value it will get here.

Setting hereWhat the other keyboard calls it
Number rowNumber row
Key popupPopup on key press
Vibrate on key press, Vibration lengthVibration, and its length in milliseconds
Sound on key press, Key sound volumeSound, and its volume
AutocorrectAutocorrection
Automatic capitalsAuto-capitalization
Double space types a periodDouble-space period
Suggestions, Emoji suggestionsShow suggestions, emoji suggestions
Glide typingGesture or glide input
Long press delayLong press timeout
Key heightKeyboard height, from its scale (1.25 times is 60 dp here)
Split keyboardSplit keyboard
Light or darkThe light, dark or black colour set, or following the system
Press and hold on toolbar keysHeliBoard and LeanType’s toolbar key codes: the long press you set for each toolbar key

A toolbar key’s long press comes across only where you changed it in HeliBoard. The long presses HeliBoard ships with (Undo to redo, Copy to cut, Clipboard to paste and the rest) are the pairs this app holds to already. A long press set to repeat the key is left out, since here that is the cursor tools’ own setting, and so is one with no tool here, like clearing the clipboard history.

Values are kept inside this app’s own limits: a vibration of 100 ms becomes 60 ms, the most this app allows. A value that only means “use the system’s”, like HeliBoard’s default vibration length, is left out, because this app already does that when nothing is set. Settings that look alike but measure something else, like each keyboard’s autocorrect strength, are left out rather than guessed at.

Settings are written the way a restore of this app’s own backup is: the keyboard reads its settings back afterwards, and puts everything back as it was if they no longer read.

The list ends with what the backup holds that has nowhere to go here, so nothing disappears without a word:

  • Clipboard history. Never imported. It belongs to the other keyboard and is often private.
  • Symbol and number layouts. This app draws those from its own.
  • Theme files the app cannot read, such as a damaged one.
  • Custom fonts and background pictures from HeliBoard.
  • Language models and voice data from FUTO, which are that keyboard’s own engines.
  • Shortcuts on FUTO’s added words. The words come across; the shortcuts on them do not.

HeliBoard keeps the words you add by hand in Android’s own personal dictionary, not in its backup. Bring those across from WM Keyboard  Typing  Suggestions  Personal dictionary with its import from Android.

WM Keyboard  Layout & size  Key layouts  Import from another keyboard

Pick the file. The app reads it, then puts one dialog in front of you before it saves anything. Only one thing on that dialog needs an answer: the language. Everything else tells you what the conversion did, and the Import button is your confirmation.

The FlorisBoard and HeliBoard formats do not record one. There a layout is a grid and the language comes from the keyboard’s own settings, so the file itself cannot say whether a Cyrillic grid is Russian or Ukrainian. A FUTO layout does state its languages, and the picker starts from that instead of from a guess.

That matters more here than it sounds. The language picks the dictionary, the autocorrect, the script rules, dictation, and how the shift key behaves. The app guesses from the letters on the keys and shows you the guess, and you can change it before you import. There is no silent default.

A foreign layout file carries one grid, and the keyboard that reads it draws the symbols and number layers itself. So the app supplies those, and the imported layout uses WM Keyboard’s built-in symbols and number grids.

The frame around the letters gets the same treatment, so an imported layout ends the way the built-in ones do:

  • The last letter row gets ⇧ at the start and ⌫ at the end, both one and a half keys wide.
  • Below it goes the usual bottom row: ?123, comma, 🌐, a spacebar four keys wide, full stop and ⏎.

What the file says still wins where it says something:

  • A delete key the file placed stays where it is. The layout then gets no shift key added either, because placing the delete key yourself is how a FUTO layout says it wants no automatic shift key.
  • A bottom row the file wrote is read, not thrown away. Its comma and full stop keep their own characters and press-and-hold letters, so a Bengali ।, an Urdu ۔ or an Arabic ، comes across. A key the usual row has no place for, such as a tab key, keeps a place next to the spacebar. A letter on that row, such as an apostrophe or a ZWNJ key, moves up to the end of the last letter row.
  • A key the letter rows already have is not added twice. A PC-style grid with its enter key on the home row, or its comma and full stop beside the letters, gets no second one.

HeliBoard’s text format and FlorisBoard’s character grids have no way to write any of these keys, so those layouts always get the whole frame. A Keys Cafe layout is the opposite case and gets none of it; see below. A layout with a key taller than one row keeps the shape its author gave it, because moving keys would slide them under the tall one. It still gets a delete, space and enter key if it has none, and the dialog names the ones it added.

Some keys in those formats do things WM Keyboard reaches another way: voice input, the clipboard panel, the settings screen, the suggestion-bar toggles. Those are tools here rather than keys, so they are removed and the dialog names the codes it removed. A key that looked right and quietly did nothing would be worse.

A handful of keys convert to the closest match rather than an exact one, and the dialog counts those too. Delete-word becomes a plain delete; the second symbols page folds onto the symbols key.

HeliBoard’s text format has one field per key, so it spells everything in the label. A key that says delete is the delete key, $$$ is the local currency, aa|bb shows aa and types bb, and abc|!code/-7 names a code outright. The app reads all of it:

In the fileBecomes
delete, shift, space, action, zwnjThat key
alpha, symbol, numpad, emoji, language_switchThe matching layer or switch key
period, commaThe punctuation slots, with this keyboard’s own popups and its email and URI behaviour
ctrl, alt, meta, fnThe modifier keys
comA .com key. The other keyboard localises this one, so it is counted as approximated
$$$, $$$1 to $$$5Currency signs. Also localised there, also counted
aa|bbA key drawn aa that types bb
x|!code/-7Whatever that code means, here delete
\spaceA key that draws the word “space”. A backslash escapes the whole label

A name this keyboard has nothing for, such as dpad, is removed and named on the dialog. An icon name (!icon/previous_key) refers to the other keyboard’s own drawable, so the key keeps whatever its action draws here and the dialog counts the loss.

Keys that change with the shift key or the field

Section titled “Keys that change with the shift key or the field”

A JSON layout can make one key conditional: case_selector for the shift state, variation_selector for the field, keyboard_state_selector, layout_direction_selector. HeliBoard’s own Dvorak layout is written this way.

One slot here holds one key, so the app keeps the resting branch: unshifted, an ordinary text field, left to right. The dialog counts the keys that lost a branch.

case_selector is the exception and loses nothing. Its two branches are exactly this keyboard’s key and shift-label pair, so both cases come across, and a shifted letter that is only the plain uppercase is left for the keyboard to produce on its own.

An auto_text_key changes case with the shift key over there, whatever case its code is written in. The app takes the lowercase as the key’s own and leaves the capital to the shift key. Some published grids write a lowercase label on the code of the capital letter (FlorisBoard’s Rusyn grid does this for ї, ы and ё), and those keys would otherwise type the capital with no shift.

The other keyboard writes a popup’s options inside the popup list, wrapped in exclamation marks. !fixedColumnOrder!4 and !autoColumnOrder!4 become that key’s Alternate columns, which you can change afterwards in the layout editor. !hasLabels!, !needsDividers! and !noPanelAutoPopupKey! ask for drawings this keyboard decides for itself and are dropped. None of them is a letter, so none ends up as a key you can type.

HeliBoard keys can carry a labelFlags number, which is how a layout says that one key’s label is a word rather than a letter and should be drawn at a different size. Layouts with unusual key captions need it to look right.

The app reads it. Four of those flags set a size, and each one becomes that key’s Label size in the layout editor, so you can see it and change it afterwards:

Flag in the fileLabel size here
followKeyLargeLetterRatio×1.15
followKeyLetterRatio×1
followKeyLabelRatio×0.68
followKeyHintLabelRatio×0.44

Two more need no size at all. disableKeyHintLabel turns on Hide the corner hint for that key, which means the same thing. autoScale and autoXScale ask for a label that shrinks to fit its key, and WM Keyboard already does that to every label on every layout.

Write the number in decimal or in hex ("labelFlags": 320 and "labelFlags": "0x140" are the same key). An exported file uses decimal.

The rest of the flags ask for a text style this keyboard has no form of, such as a monospaced or an off-centre label. Those keys keep their size and lose the style, and the dialog counts them.

FUTO Keyboard writes its layouts in YAML, and publishes its own as a repository of them. Pick one with the same Import from another keyboard button; the app tells a YAML layout from a JSON one by the document itself, not by the file name. Tapping one in a file manager works too. .yaml is not claimed by name, because that would offer WM Keyboard for every YAML file on your phone, but the YAML content types are, and the same name:-and-rows: test recognizes the file. Either way the language is confirmed before the layout is saved.

Most of that format reads straight across, because FUTO’s keyboard descends from AOSP’s and so its key specs are the ones already read here: a|b, !code/, !icon/ and the same !autoColumnOrder!4 popup markers. A row written as q w e r t, as [[a, ą], b], or as a list of {type: base, spec: …} objects all work, and so does type: case, which keeps both cases the way a FlorisBoard case selector does. When the key has no shifted branch, its shiftedManually one is the shifted letter. That is how a script with no capital letters writes its second layer: Korean ㅂ over ㅃ, and the Khmer, Myanmar and Bengali layouts.

Four differences:

  • It is the one format that states its language. languages: [lt] seeds the language picker with a fact rather than a guess from the letters. A language this app does not have falls back to the guess.
  • The number row is dropped, because this app adds one from a setting and keeping the file’s would give the layout two. A layout that sets numberRowMode: AlwaysEnabled, which is how the PC-style arrangements carry their backtick and bracket keys, keeps its own.
  • Its bottom row becomes this app’s, as above, keeping the file’s own comma and full stop. The $action key, which the user sets in FUTO’s own settings, is dropped and named.
  • The alternate pages are dropped and named. $alt0 and its siblings switch to a whole second grid, which has no slot here, and a key that switched to nothing would strand you on it. The symbols and number layers are this app’s own for the same reason, and layoutSetOverrides names layouts by ids that mean nothing here.

$contextual becomes the comma slot, which does the same job from the same signal: / in a web address, @ in an email field.

Keys Cafe is Samsung’s Good Lock module for Samsung Keyboard, and its Make your own keyboard screen is a key-by-key editor for the whole grid. A keyboard made there is saved and shared as a .kcf file, which is what people trade on the Samsung community forums. Pick one with the same Import from another keyboard button, or tap it in a file manager: WM Keyboard claims the .kcf extension, and it also recognizes the file by its contents, so a renamed one still works.

A .kcf is a layout and only a layout. Keys Cafe’s Style your own keyboard colours and effects are a Samsung theme, not part of this file, and nothing of them comes across.

This is the one format that carries the whole frame. Keys Cafe writes the shift and delete keys, the symbols key, the space bar, enter and the bottom row exactly where you put them, and a bottom row with a letter or two beside the space bar is often the point of the file. So the import adds nothing and moves nothing: the grid lands as laid out, and the layer is marked to keep its bottom row as drawn, so the Bottom row settings (the 🌐 key’s place, comma and 🌐 swapped, the emoji key) leave it alone. Only a file whose author removed the space bar or the delete key gets WM Keyboard’s frame put round what is left.

  • The number row is kept as this layout’s own number row, digits and their fraction popups included. It shows while the number row is on under Layout & size, the same as any layout’s.
  • The corner symbol is the first press-and-hold entry, so it stays the corner hint and a long press still types it, as it did on Samsung Keyboard. The key’s other press-and-hold letters follow it. Samsung Keyboard keeps a second list for the shifted state; where that list is more than the capitals of the first, the dialog counts the key.
  • The language is a fact, not a guess. The file states a language and a country, and the picker starts from it.
  • Widths follow the file. A plain key is one unit, a wider shift or space bar keeps its proportion.
  • A function key this app does not know is removed and named by its code, the same as a HeliBoard key would be. One real export has been read, so the known codes are the delete, shift and symbols keys, space and enter. If the dialog names a code and you know what that key was, say so in an issue and it is one line to add.

Multiling O builds its layouts out of text, and its users share them as text: in forum posts, gists and READMEs, for scripts few other keyboards ship. Copy the text into a .txt file and pick it with the same Import from another keyboard button, or open the file from a file manager. Three forms are read:

  • A DIY layout, a JSON object with a title and an onScreen object holding the rows of each page (main, sym, altGr and the rest). It is the whole keyboard, bottom row included, so it is kept as laid out, the way a Keys Cafe layout is. A layout copied out of a share link, with %0A and %22 in it, reads the same.
  • A DIY+ layout, the block from OK_Layout_Begin to OK_Layout_End. Its rows come in blocks of four: the letters with a row of digits on top, the same rows shifted, then the symbols, the AltGr page, the shifted AltGr page and the shifted symbols. It has no shift, delete or bottom row of its own, so it gets this app’s, as above. The row of digits becomes this layout’s number row.
  • A settings export, the block from OK_Settings_Begin to OK_Settings_End that Multiling writes under Misc → Import | Export. It holds every layout you made, each filed under the language it was made for. The dialog lists them all and adds them all in one step, each with that language, or with the one its letters suggest where this app does not have the language. The colours in the export are saved as a theme beside them. Landscape copies of a layout are skipped: this app sizes one grid for both.

A row is a string of keys, and each part comes across like this:

  • A character is a key, and a space is a gap. [] straight after a key makes it one key wider, as [SPACE][][] does.
  • Named keys ([SHIFT], [DEL], [ENTER], the arrows, copy and paste, F1 to F12 and the rest) become the same keys here. [WDEL] is a plain delete key, because swiping left on delete removes whole words here.
  • [4D:…], [1+4:…] and [3+2:…], the swipe keys, keep their swipes. The first character is the tap and the rest are the eight directions, the way a MessagEase pad has them. A swipe that runs a key (a cursor move, copy, a page switch) keeps doing that. A swipe on a key whose own swipe is already taken here, such as the delete key or the space bar, is removed and counted.
  • [XK:…] types its first character, with the rest on its press and hold.
  • [MT:…] cycles through its characters on repeated taps.
  • [MC:…] types more than one character, under its own label when it gives one. A shortcut such as [MC:[CTRL]z:undo] becomes that key press. Multiling’s date and time macros are removed and named.
  • [U+0915] is the character with that code.
  • [SYM:.], [ALTGR:,] and [123:…] type their character on a tap and open their page when you swipe from them in any direction. The page is on their press and hold too.

The pages come across with the layout. sym and symShifted become this layout’s two symbols pages. AltGr, 123 and Edit become pages of the layout, opened from the same keys as before; on a DIY+ layout, swipe from the comma key or hold it to open AltGr. A shifted page laid out key for key like the page it shifts becomes the shifted forms of those keys. Multiling’s tool key opens a menu that this app keeps on its toolbar, so it becomes ?123 on a letters page that has no other way to the symbols, and ABC on a page that has no other way back. A key this app has nothing for, such as [INFO] or [PREDICT], is removed and named in the dialog.

Unexpected Keyboard and CleverKeys layouts

Section titled “Unexpected Keyboard and CleverKeys layouts”

Unexpected Keyboard has no layout editor of its own: a custom layout is a block of XML pasted into its settings, and people share them that way, in the project’s community layouts repository, in gists and in issue threads. CleverKeys reads and shares the same XML. Save the XML as a .xml or .txt file and pick it with the same Import from another keyboard button, or open the file from a file manager. A CleverKeys backup brings its custom layouts with it; see Whole backups.

  • The swipes stay swipes. Each key’s tap (c, or key0 in older files) is the key, and the eight corner and edge swipes (nw, ne, sw, se, n, s, e, w, or key1 to key8) become the key’s flick arms, drawn on its face as they were. A swipe that types text is on the key’s press and hold too. A swipe that runs a key, such as a cursor move or copy, keeps doing that. A swipe on a key whose own swipe is already taken here, such as delete’s ne="delete" or a space bar’s cursor swipes, is removed and counted.
  • Swipe typing still works on the letters. A short swipe that stays on the key is the flick; once your finger leaves the key for the next letter, the stroke is a glided word. A key with a cursor or delete swipe keeps its whole stroke, so swipe typing never starts on it. A letter reachable only through a dead key, such as â behind the French AZERTY’s circumflex, isn’t on the glide grid, so a word with one in it has to be tapped. The rest of the language still glides (see when a layout can’t spell the language).
  • Named keys (shift, backspace, enter, the arrows, copy, paste, undo, F1 to F12 and the rest) become the same keys here. switch_numeric opens the ?123 page and switch_forward changes language. The accent keys (accent_aigu, accent_grave and the rest) become dead keys. legend:'text' types the text under that label, legend:keyevent:85 sends that key code, and a macro of modifiers and one letter, such as Cz:ctrl,z, becomes that key press. A key this app has nothing for, such as compose or switch_greekmath, is removed and named in the dialog.
  • A loc key is skipped. Unexpected Keyboard shows those only when a setting adds them, so nothing is said about them.
  • The bottom row is this app’s, as above, unless the file says bottom_row="false" and has its own space bar and delete key. Such a grid is kept as laid out, the way a Keys Cafe layout is.
  • The number row is this app’s, unless the file says embedded_number_row="true". Then its row of digits becomes this layout’s own number row.
  • Gaps and widths follow the file. A key’s shift becomes a gap to its left, and a row that starts with one stays aligned to the left, as it was. Row heights come across too.
  • <shift a="i" b="İ"/> in the modmap becomes that key’s shifted form. The Fn and Ctrl mappings have no place here and are left out.
  • The language is the one a CleverKeys layout names in its language attribute, or in a backup the one you set for it there. Otherwise the picker starts from the letters on the keys.

Layouts made for a computer (Windows, macOS, Linux)

Section titled “Layouts made for a computer (Windows, macOS, Linux)”

Plenty of keyboard layouts for smaller languages were only ever made for a computer. Someone built one in Microsoft’s Keyboard Layout Creator or in Ukelele, or wrote an XKB file for Linux, and put it on a university page or a forum. WM Keyboard reads all three. Pick the file with the same Import from another keyboard button, or open it from a file manager.

FileMade withHow the app knows it
.klcMicrosoft Keyboard Layout Creator (MSKLC), WindowsThe extension, and its KBD, SHIFTSTATE and LAYOUT sections. MSKLC saves these files as UTF-16, and the app reads them that way
.keylayoutUkelele, or by hand, macOSThe extension, and its <keyMapSet>
XKB symbols fileLinux, the files under /usr/share/X11/xkb/symbols/Its xkb_symbols "name" { blocks. These files have no extension, so only the contents count

A computer keyboard has about 48 keys that type something, with four levels on each: plain, Shift, AltGr (Option on a Mac), and Shift with AltGr. A phone grid has room for about 30 keys and two levels, so the layout gets folded down:

  • The 26 letter keys stay where they are, whatever they type. The keys around them come across too when they type a letter, at the end of their row: Danish æ ø å, a Dvorak s where QWERTY has its semicolon. Keys that type only punctuation are left to this app’s symbol pages.
  • The number row becomes a row of the grid only when five or more of its keys type letters, the way the Czech, Slovak and Lithuanian layouts are built. With fewer, each letter goes on press and hold of the letter it is built on (é on e, which is where AZERTY users reach it on a phone anyway), or onto the end of the shortest row when it is not built on one (German ß).
  • Shift comes across as each key’s shifted form, where that is more than the capital letter.
  • AltGr goes on press and hold of the same key, first, so the corner hint shows what the key’s AltGr level was.
  • Dead keys go on press and hold too. Every letter on the grid gets the accented letters the file’s dead keys make of it, so a dead acute puts á on a and é on e. A dead key that sits on one of the letter keys keeps its place and works as a dead key here.
  • Nothing is dropped without a word. Characters on the left-out keys that are not plain ASCII or digits, such as Armenian ՝ or Ethiopic ።, go on press and hold of the full stop. The dialog says how many.
  • Shift, delete and the bottom row are this app’s, as above.

A .klc names its language (LOCALENAME), and the picker starts from it. The other two do not, so the app guesses from the letters as usual.

An XKB file usually holds several variants. The import offers each one that is a whole layout, the default first, and adds them all at once; parts that only set up modifier keys are skipped. A variant often builds on another with include "us(basic)". An include of a variant in the same file is followed, and so are the plain US and Latin bases, which are built in. An include of any other file cannot be, since you opened only the one file, so the dialog names it and you know which keys may be missing. Includes that only set up modifiers, such as level3(ralt_switch), carry no characters and are not mentioned. An XKB dead key (dead_acute) puts its accent on a letter the way Unicode composes them, because the real tables live in your Linux system’s Compose file, not in the layout.

Some letters can be written two ways in Unicode: a base letter plus a mark, or a single character that means the same thing. Bengali, Devanagari, Gurmukhi and Oriya all have letters like this. WM Keyboard’s cluster shaping and its backspace rules use the single-character spelling, so the app rewrites the other one on the way in. Without it a key looks correct and then deletes half a letter at a time.

WM Keyboard  Typing  Suggestions  Custom dictionaries  Import word list

Every AOSP-derived keyboard shares one dictionary ecosystem, and for most languages a compiled .dict is the only form the word list exists in. All of it imports here as it is: the .combined source lists a dictionary repository publishes, the compiled .dict files HeliBoard, LeanType and FUTO download (including the ones pulled out of a GApps package), and the version 4 dictionaries those keyboards write on the device.

An AOSP dictionary holds three things, and each goes where this app keeps that kind of thing:

In the dictionaryHere
Words and their frequenciesAn ordinary text word list
Word pairs (bigrams), and word triples in a version 4 fileNext-word predictions, like a downloaded Word pairs pack
Shortcuts, such as omw for “on my way”The first suggestion when you type the short form in full, and a trigger for glide typing

When the file has more than words, a dialog asks which of the three to import. The pairs and shortcuts are stored beside the word list and follow it: switch the list off and they stop, delete it and they go. A list imported for its pairs alone still shows on the Custom dictionaries screen, with no words in it, so there is something to switch and delete.

A .dict is unpacked into an ordinary text list at import, so everything the Custom dictionaries screen does to a list you wrote yourself works on it too: the word count, the switch, the trash icon, and taking a single word out from the suggestion strip.

Frequencies are 0 to 255 over there and 0 to 10000 here, so they are scaled rather than copied. Copying them would drop every imported word below every bundled one. A pair’s strength is scaled onto the counts of a downloaded pack, where the strongest pairs weigh about as much as a pair you typed a few dozen times yourself.

A shortcut the source keyboard applied on its own (a “whitelist” shortcut) is offered here, never applied. A file built with a codePointTable, which spells the most common letters of a language in one byte each, is read through that table.

Your learned words from HeliBoard or LeanType

Section titled “Your learned words from HeliBoard or LeanType”

Those keyboards keep what they learned from your typing in a user history dictionary, in the version 4 format. That format is a folder of two files, NAME.header and NAME.body, so there are two ways in:

  • Make a backup in HeliBoard or LeanType and import the .zip. The app takes out every dictionary in it, one list each, and ignores the layouts, blacklists and images a backup also holds. Each dictionary shows the language code it was written for, so you can leave out the ones for another language.
  • Or select the .header and the .body together in the file picker.

A user history keeps counts rather than frequencies, so a word you typed often there arrives ranked higher, and a pair you typed twelve times weighs twelve times the pair typed once. Words that keyboard had blacklisted do not come across.

Only one shape is refused: revision 402 of version 4, which no current keyboard writes.

See Dictionaries & words for the screen itself.

WM Keyboard  Typing  Suggestions  Personal dictionary  Import a Gboard dictionary

In Gboard, open Settings, then Dictionary, then Personal dictionary, and choose Export from the menu. You get a PersonalDictionary.zip. Open it from the row above, from a file manager, or share it to WM Keyboard. The file can also be the dictionary.txt inside the zip, which is the shape community packs of LaTeX symbols and emoji codes ship in.

Each entry in the file is a word, a shortcut for it, or both, and the two go to different places:

  • A word with no shortcut goes into your personal dictionary as a word you added by hand, capitals kept. A phrase such as “New York City” comes in as its separate words, the way an entry from Android’s dictionary does.
  • A shortcut becomes a snippet in a folder called Gboard, so you can switch the whole set off at once. Gboard never types a shortcut out by itself: it shows the word as a suggestion. The snippet does the same, because each one is set to ask first. A shortcut Gboard maps to several words becomes one snippet that offers all of them.

The dialog counts both halves before anything is written. The locale Gboard saved with each entry is not used, since the personal dictionary here is shared by every language. Picking the same file from the Text expansion import adds the shortcuts only, and says how many words it left for this screen.

WM Keyboard  Languages & layouts  Chinese  Chinese options  Import from FlorisBoard

FlorisBoard’s other kind of .flex is a language pack: an SQLite database of the shape-based Chinese tables, where a code spells a character by how it looks rather than how it sounds. Those are the same tables this app’s own Cangjie and Stroke packs hold, so a pack you already have fills one without a download.

The rows are written exactly where a download would have put them, so everything else on that screen keeps working on it: the row says Downloaded, the keyboard picks the table up at the next field you tap, and the trash icon removes it.

Three things to know:

  • Only Cangjie and stroke land. A pack often holds Wubi, Zhengma, Boshiamy and others as well, and this keyboard has no way to type those, so a table for one would be a large file that changed nothing. The app names the tables it found back to you instead. Cangjie Quick needs no table of its own: it is the same codes queried differently.
  • How common each character is survives the import. The pack FlorisBoard ships stores that as a fraction between 0 and 1, in a column its own converter labels as a whole number, so it is read by what the file actually holds rather than by what the column claims. Without that every character imported as equally common, and which one a code offers first is decided by exactly this number.
  • A stroke table is rewritten as it is read. Those tables spell the five strokes as the letters h s p n z; a stored code here is always 1 to 5. Without that translation every row would be dropped for having a code no key can produce.

Pick the wrong .flex and the app says so rather than failing: a theme file is named as a theme, with Themes as the place to take it.

WM Keyboard  Layout & size  Key layouts  Import an input method

Many input methods are shared as data files rather than as apps: a .cin table for gcin or OpenVanilla, a Rime schema and its dictionaries, an m17n .mim file for ibus. WM Keyboard reads all three and makes each one a keyboard layout of its own. The method’s data is kept with the app, and the layout types through it.

Pick every file the method needs at the same time. The picker takes several files at once, and the app works out which file is which from what is inside them, so the order does not matter.

  • A .cin table is one file. Each code types the entries listed for it, and the suggestion strip offers them as you type, an exact code first and then the codes that start with what you typed. The keys show the caps the table names in %keyname, so a Cangjie table puts 日月金 on the keys and an Array table its 1- 2⇡ positions. Keys the table uses besides letters, such as Array’s , . / ; or Boshiamy’s [ ] ', get a key each.
  • A Rime schema needs the .schema.yaml, the .dict.yaml it names, every table that dictionary imports, any shared file its rules come from, such as pinyin.yaml or zhuyin.yaml, and the word list the dictionary ranks by: essay.txt from rime-essay, or the file its vocabulary: line names (essay-cantonese.txt for rime-cantonese). Without the word list the import still works, but most dictionaries state no counts of their own, so every character ranks the same, and a pinyin dictionary has few phrases: Rime builds them from that list, and so does this app. The confirm dialog names any of these files that were not picked. A schema that converts syllables (Rime’s script_translator: pinyin, Jyutping, Wugniu, Zhuyin on terra_pinyin) converts whole phrases with the same decoder as the built-in Chinese layouts, prefix commit and learned picks included. A code schema (table_translator: Cangjie 5, Array 30, Wubi 86) works like a .cin table. The schema’s spelling rules (speller/algebra) are applied when you import, so tone-free and abbreviated spellings and the schema’s own keys for Zhuyin work as they do in Rime. A dictionary picked without a schema works too, with no spelling rules.
  • An m17n .mim is a program of rules, not a table. The app runs those rules itself, so a key can change the letter before it the way it does in ibus: in Hindi ITRANS k shows क्, ka gives क, and a space after k leaves क. The keys are the ordinary QWERTY keys, with Shift where the method uses capitals, and the corner of each key shows what it will write next. Turn the hints on under WM Keyboard  Languages & layouts  Hindi  Key hints  Show the letter each key types (or the same row on your method’s language) to see them. A method that includes another needs that file picked too.

The import ends on a confirm dialog that says what was read, how many entries or rules came across, and what was left out. It has a Language row: an m17n file names its language, and for the others the app guesses from the text the table writes (Chinese for Han characters, Cantonese for a table whose name says Jyutping). Set it before you import. The dialog offers Import and Import and turn on.

What does not come across:

  • The space bar as a key. Some Zhuyin schemas type the first tone with the space bar. Here the space bar always types a space; leave the tone out, as the schema’s own toneless spellings allow.
  • m17n plug-ins. A method that calls a compiled module (Anthy, ispell) or hands keys to another input method keeps the rest of its rules, and those keys do nothing. The confirm dialog says so.
  • m17n candidate lists. Where a method offers a list of choices for a key, the first choice is taken.
  • Text before the word. An m17n rule can look at, and delete, text you typed earlier in the same word. It cannot reach text from before the word started.

Deleting the layout deletes the method’s data with it, unless a copy of the layout still uses it. An exported layout file names the method but does not carry its data, so on another phone it types its own key caps until you import the method there too.

WM Keyboard  Appearance  Keyboard themes  FlorisBoard

A .flex file is FlorisBoard’s theme package. Pick one and the app converts every theme inside it. You can also open a .flex straight from a file manager.

A FlorisBoard extension that holds both a day and a night version becomes one theme with two looks, not two separate entries, and an extension with more themes than that becomes one theme with that many looks. The first look heads the family and the rest become variants of it. The family takes the title the extension declares for itself, or the first look’s own name when it declares none. Auto theme addresses the looks individually, so you can still put the day one in one slot and the night one in the other under WM Keyboard  Appearance  Keyboard themes  Auto theme. The result message says so too: “The app saved name with 2 looks.”

Converted themes are saved but not turned on. They go into your themes list for you to look at first, and the theme editor is where you finish the parts that did not carry over.

Open the .flex from a file manager and the dialog puts a number on it: “The app can use 34 of the 52 style rules in this file.” That number counts the rules that changed something the app draws, not the rules it merely recognised. A rule that only sets text wrapping names a part this app has and still changes nothing, so it does not count. That dialog is also where the list below shows up, one line per thing that had nowhere to go.

Colours mostly land. These all have somewhere to go:

  • The board, the keys, the pressed key, the enter key, the function keys, borders and per-key colours.
  • The key popup and its border, and the corner hint. A theme that styles only the emoji popup gets that bubble for both.
  • The toolbar: the tool icons, the circle behind them, the active toggle and the glyph on it.
  • The suggestion strip: the suggestion text, the quieter second line, the dividers, the clip chip, and a chip’s selected colours.
  • The panel cards, the bottom sheets, the navigation bar band and the glide trail.
  • Key and hint text sizes, bold labels, and the corner shape of keys, popups, chips, cards and menus.
  • The shape of a single key. A theme that makes only the enter key round keeps it round here.
  • Shadows. The lift under the keys, the popup, the panel cards and the toolbar tools. Nearly every bordered theme raises its keys 2 dp, and without this they came across flat. The keys’ shadow-color comes across too, as Key shadow colour.
  • The selected highlight in a popup: the colour behind the letter your finger is on when you hold a key, and behind the selected row of the language list.
  • The one-handed rail beside the keyboard, which had no way to differ from the board before.
  • The floating keyboard’s handle, which takes the toolbar’s own colours here.
  • The panels. A clipboard notice’s heading and body, the buttons inside a panel, the icon buttons on a panel’s header, the rows of the language list, the emoji keys, and the clipboard’s dialogs. None of these is a separate colour here, so each lands on the one the keyboard already draws it with.
  • A board background image and a key texture, and how the texture is told to fit its key.
  • Keys named the 0.5 way. A newer stylesheet names a key by what it types (key[output=\@k3:action/enter`]`) rather than by its key code, and FlorisBoard’s own themes write both. A theme written only the newer way used to come across with no enter key colour at all.
  • A font the theme ships with itself. A .flex can carry its own typeface, declared as @font \ndot`and pointed at withfont-family`. Two of the six themes on the FlorisBoard addon store do exactly that, and for one of them the dot-matrix face is the theme. The file is installed as a font add-on of its own, under the name the stylesheet gave it, and the converted theme is set to use it. It then appears in WM Keyboard  Appearance  Keyboard font like any other installed font, and other themes can use it too.

Colours that follow the wallpaper are read too. A FlorisBoard theme may name a Material You role, such as dynamic-dark-color(surfaceContainerLow), instead of a fixed colour. On Android 12 and later the app resolves those against the same system palette FlorisBoard reads, so a theme written that way arrives with its colours rather than empty. Two of the most-used theme packs are written entirely this way.

On a phone below Android 12 there is no such palette, so those colours resolve against stock Material instead and the dialog says that rather than claiming your wallpaper was read.

And they keep following it. The converted theme remembers which Material You colour each part came from, so when you change your wallpaper the keyboard moves those parts onto the new colours, the same as FlorisBoard does. The theme’s Follow wallpaper colors switch in the theme editor is on after the import; turn it off to keep the colours you have today. A colour you change in the editor stays as you set it. A theme imported before version 0.5.13 has no such record: import it again to get this.

Themes from other keyboards, and FlorisBoard themes written in fixed colours, can follow the wallpaper as well. They start with the switch off, and when you turn it on each colour keeps its lightness and takes your wallpaper’s hue.

FlorisBoard styles a much larger set of keyboard parts than this app draws, so the rest is reported rather than approximated:

  • Per-corner radii. Keys here have a single corner size.
  • Spacing on single elements. The key gap is set for the whole keyboard.
  • A font the theme only names. Some themes name a font family without shipping it. There is nothing to install in that case, so install the font yourself and pick it in the theme editor. A theme that sets font-family: inherit, which is what both of the big theme packs do on every rule, is asking for no font change at all, so nothing is reported for it.
  • Text wrapping and alignment. How many lines a label may take, where it is cut and how it is aligned are set by this app, not by the theme.
  • The landscape text editor. When a field fills the screen in landscape, Android draws that editor, not this app, so a theme cannot colour it here. The dialog names the parts it could not use rather than saying only that there were some, and for the usual theme packs this editor is most of that list.

If a key’s text colour would be unreadable on what sits behind it, the app drops the imported colour and picks a readable one, and says so. The test is made against what you see: a borderless theme’s keys are transparent, so its labels are judged against the board showing through rather than against the empty key.

WM Keyboard  Appearance  Keyboard themes  HeliBoard

Those keyboards have no theme file. A theme is a line of JSON that you copy out of the menu at the top of their colour screen, which is why their theme collections and their whole sharing culture live in forum posts rather than in downloads. So the HeliBoard button asks where the theme is: Paste takes it off the clipboard, Open a file takes a .json somebody saved it into. LeanType is a HeliBoard fork whose colour screen is unchanged, so its themes are the same thing.

Both of that keyboard’s export shapes are read:

  • The ten named colours, which is what its few colours and more colours modes export. The board, keys, functional keys, spacebar, key text, hint text, suggestion text, spacebar text, accent and glide trail.
  • Every internal colour role, which is what its all colours mode exports: forty-odd values covering the popups, the suggestion strip, the toolbar, the emoji board, the clipboard chips and the navigation bar. This is the richer of the two and is what a carefully built theme is usually in.

A colour that keyboard worked out for itself stays worked out. Its export marks each of the ten as chosen or derived, and a derived one is left unset here so this app derives it in turn. Freezing it in would leave you unable to tell a colour you picked from one that was guessed.

Two colours land on single keys rather than on the board: the spacebar’s own background and label, and the shift key’s icon colour, all of which become per-key styles you can see and change in the theme editor.

The emoji board’s own colours land too. That keyboard’s all colours mode states seven values this app used to read and then drop: the emoji search field’s fill and text, the emoji glyphs, the category tabs, the remove-suggestion icon, the second row of suggestions and the enter key’s long-press sheet. Each of them now reaches the surface this keyboard draws the same thing with.

The result message counts what landed: “The app saved Midnight and used 19 of its 19 colours.” That count is the roles that actually reached a field, not the roles the app recognises. Two of its roles may answer the same question here, and only the first one present is read. Under the count is the same list of what did not come across that the other two imports show: colours the file left for the keyboard to work out, colours stated for parts this keyboard has not got, and text that had to be replaced to stay readable.

A theme is saved rather than switched on, the same as a FlorisBoard one, so you get to look at it first. Day or night is decided from the board colour, since neither shape records it.

WM Keyboard  Appearance  Keyboard themes  Multiling O

Multiling O has no theme file either. A theme is the colours part of its settings export, a block of lines from OK_Settings_Begin to OK_Settings_End, and themes are shared as that block or as a link to a page with the block in it. The Multiling O button asks where yours is: Paste takes the block or the link off the clipboard, Open a file reads a text file you saved it in. A whole settings export works too, and so does opening it from a file manager.

The nineteen colours on Multiling’s Color screen land like this:

MultilingHere
BackgroundThe board
Key1, Text1The letter keys and their labels
Key2, Text2The other keys (punctuation, shift, delete) and enter
HighlightA pressed key
Key1 shadowThe key shadow colour, with a small lift
Popup, Popup textThe key popup
Suggestion bar, Suggestion bar textThe suggestion strip
Sub-text1 (or Sub-text2)The corner hint
Space bar, Space bar textThe space bar’s own style
Suggestion highlightThe accent

A colour of 0 is how that screen says “none”, so it stays unset here and this app works it out. The key corner radius, the label size and bold labels come across too. A shadow behind the key labels has no place here, and a wallpaper is only a switch in the text, never the picture; the result message says so when a theme has either.

WM Keyboard  Appearance  Keyboard themes  FUTO

A FUTO theme is a .zip: a settings file and the pictures it names. Pick one with the FUTO button, open it from a file manager, or bring all of them at once with a FUTO backup (see Whole backups). Both of FUTO’s settings files are read: theme.txt, the hand-written format themes are shared in, and config.json, what FUTO’s own theme editor saves.

FUTO paints its keyboard from a handful of its colour roles, and those are the ones that come across:

FUTO roleHere
keyboard_surfaceThe board, and the suggestion strip
keyboard_container, on_keyboard_containerThe letter keys and their labels
keyboard_container_variantThe other keys (shift, delete, symbols)
keyboard_container_pressedA pressed key
primary, on_primaryThe enter key, the accent and the swipe trail
keyboard_pressThe long-press popup
on_backgroundThe suggestion text
hintColor (editor themes only)The corner hint; otherwise the label colour at half strength, as FUTO draws it
navigationBarColor (editor themes only)The navigation bar

The other thirty-odd roles colour FUTO’s own menus and have nothing to fill here. Key borders off becomes the None key shape, labels on the bare board. The key roundness becomes the corner radius (FUTO’s 9 dp a step), and the label size and a heavy label weight come across from a theme.txt. A background picture comes across with its opacity, and a font in the file is installed and used.

What does not come across, and the dialog lists whichever applies:

  • Pictures drawn per key, FUTO’s matchrules key borders and icons. Those keys are drawn in the theme’s colours instead.
  • Colours from the wallpaper, written as system_…. This app works out its own colours for those parts.
  • An animated background shader.

Like the other converted themes, a FUTO theme is saved but not turned on.

Both style formats are read. FlorisBoard renamed several parts in 0.5 (the board went from keyboard to window, the popup from key-popup to key-popup-box), but the colours and the way they are written did not change, so a 0.4 theme converts as well as a 0.5 one. Most themes still in circulation are the older format.

WM Keyboard  Appearance  Keyboard themes  Gboard

A Gboard theme is a .zip holding a metadata.json, one or more .css style sheets in Gboard’s own dialect, and the pictures they name. It is what Gboard exports and imports, and the format the Rboard community has shared several hundred themes in. An Rboard pack is a ZIP of those ZIPs, with a picture of each theme beside it.

The Gboard button offers two ways in:

  • Open a file reads a theme or a pack you already have. A pack lists its themes first: press one to see it, or Add all to save every theme in it as its own entry.
  • Browse Rboard opens a list of the packs in the Rboard repository (GboardThemes/PackRepoBeta on GitHub). The app asks GitHub for the list only when you open that screen, and for a pack only when you press it. Each pack is checked against the SHA-256 the list gives for it before it is opened, and kept in the cache so a second look costs nothing. While Data saver is on, the screen asks before its first request, and the answer covers the packs you open from it. If the Rboard list ever changes shape, the screen says it cannot read it rather than showing a half list; a theme ZIP from anywhere still imports through Open a file. The Google Play build leaves Browse Rboard out, and its Gboard button goes straight to Open a file; the GitHub and F-Droid builds have both.

Either way, each theme ends on a dialog with a preview of it, a count (“The app can use 29 of the 139 style rules in this theme”), and a line for each loss below. Import saves it; nothing is switched on.

Key borders become two looks. Gboard draws a theme with or without key borders by a setting of its own, and a theme ships a separate style sheet for the bordered version. Both come across, as two looks of one theme, the one the theme prefers first. A theme whose border sheet changes nothing this app draws comes across with one look.

What lands:

  • The board colour, the bar above the keys, and the navigation bar band.
  • The keys, the pressed key, the function keys and the enter key, including the round badge Gboard draws behind the enter icon in a borderless theme. The space bar’s own colour and label become a per-key style.
  • Key outlines and their width, the corner size (a large one becomes a pill, and an empty shape means no key face at all), and the lift under the keys with the colour of its shadow.
  • Key text, the corner hint, the suggestion text and its dividers, the toolbar icons, the popup and its selected highlight, the glide trail and the accent. The face Gboard draws behind a suggestion becomes a chip colour here.
  • The background photo, and a separate landscape photo when the theme has one. A picture on the keys becomes a key texture.
  • The theme’s own key glyphs. More than half the themes in the Rboard repository replace the delete, shift and enter pictures with PNGs of their own, and for those themes the glyphs are the theme. They arrive as part of the theme and draw on the keys the moment you wear it: delete, shift in each of its three states, the emoji key, the globe, and enter in each of its wordings. A glyph drawn in a single colour on a transparent background (three quarters of them are) follows your theme’s colour the way a built-in icon does; one with real artwork in it draws as its author painted it. Each glyph is trimmed to what it actually draws and sized like the built-in icons, so a picture cropped tight to its edges no longer comes out bigger than the icon it replaces. See the note on icon packs below.
  • How faded a part is. Gboard sets an element’s opacity separately from its colour, and nearly every theme uses it to quiet the function keys’ glyphs. Read without it they came across at full strength, which was the most visible difference between a converted theme and the original.
  • Light or dark, from the theme’s own flag.

Gboard styles far more than this app has, so most of a theme’s rules name things with nowhere to go here: GIF and sticker search, the translate bar, Gboard’s access points. Those are counted, not listed. What a person would notice is named on the dialog instead:

  • Compiled or missing style sheets. Gboard can compile a sheet to a binary form (.binarypb) whose format is not published. The readable sheets are used; a theme that is compiled through and through is refused with a message that says so. Gboard’s own stock themes are all of this kind.
  • A glyph for a key this keyboard has not got. The space bar’s branding and Gboard’s own logo key are the two of these; the rest of a theme’s glyphs now come across. A theme whose glyphs all land is not told anything was dropped.
  • The space inside each key. Gboard pads each key separately; here one gap is set for the whole keyboard.
  • Fonts. A Gboard theme names a font and never carries the file.
  • Corners rounded one at a time, usually the top of the keyboard.
  • Pictures on other parts of the keyboard, such as the bar’s tabs.
  • Unreadable text. A key, function-key or popup text colour too close to what sits behind it is replaced with a readable one, and the dialog says so. The enter icon and the space bar label are exempt from the line: most community themes draw the first as a picture and hide the second on purpose, so a colour there is often the key’s own and was never meant to be read.

A sheet that breaks the rules is read as far as it goes. A stray ;, a nine-digit colour, a comment that never closes, a variable used before it is defined, a picture named without its extension, and a metadata.json with junk after it all happen in real themes, and none of them stops the import. Eight hex digits are read as Gboard writes them, alpha last (#FFFFFF33 is a faint white).

A theme’s own key glyphs sit underneath your icon pack and underneath any single icon you picked by hand. That ordering is deliberate: an icon pack is a standing choice about the whole keyboard, and a theme should not quietly undo one. So with no pack installed a Gboard theme’s glyphs show straight away; with a pack installed the pack keeps the slots it fills, and the theme dresses nothing.

They also travel with the theme rather than with the keyboard. Switch theme and the glyphs switch with it; export the theme and they go in the file. This is why importing a twenty-theme Rboard pack gives you twenty themes and not twenty icon packs.

  • Almost nothing is decided by the file extension. A file is read and then judged by the format tag inside it. The one exception is this app’s own theme file, which carries no tag, so a .wmtheme.json name is the only evidence a file was meant to be a theme. Tagged formats are checked first, so a layout from another keyboard renamed .wmtheme.json is still refused rather than imported as an empty theme.
  • Opening a .flex from a file manager works because the app registers that extension. If FlorisBoard is installed too, Android asks which app should open it.
  • A Gboard .zip opens from a file manager by what is inside it. .zip is far too common to claim by name, but the app is offered for ZIP files by type, and one with a Gboard metadata.json or an Rboard pack.meta at its root is recognised. A pack opened that way has no list to pick from, so Import adds every theme in it.
  • Size caps. A theme or pack is read up to 48 MB inflated, 4 MB per picture, 128 themes per pack; a downloaded Rboard pack is refused past 32 MB. Entry names are only ever looked up, never used as paths.
  • A whole backup opens from a file manager by what is inside it. HeliBoard, LeanType, FlorisBoard and CleverKeys backups are .zip files and FUTO’s is a ZIP named .backup. Neither extension is claimed, but a ZIP holding one of their settings files is recognised however it is named. Each part is read up to 32 MB, and a backup is refused past 128 MB of the parts the app keeps; FUTO’s language models are counted and skipped, never read into memory.
  • Foreign layout files are not auto-detected from a file manager. They carry no marker that identifies them, so they go through WM Keyboard  Layout & size  Key layouts  Import from another keyboard, where you have already said what the file is. This app’s own .wmlayout.json files do open from a file manager, because they carry a format tag.
  • A foreign layout over 4 MB is refused. The whole file is decoded as one string, so there is a cap, and the cap is 4 MB. Past it you get the same “The app cannot read that file as a layout” message an unreadable file gets, with nothing to say the size was the problem. No real grid is anywhere near it, so in practice this only catches a file that is not a layout at all.
  • Input method files are capped at 48 MB each and 128 MB together, and a table is cut at 500,000 rows for a .cin and 1,500,000 across a Rime dictionary and its imports. The confirm dialog says when a table was cut. .cin files in Big5 or GB18030 are read as well as UTF-8.
  • Add-on repositories stay native. Repository payloads are always WM Keyboard’s own formats; conversion applies to files you pick yourself.
  • Nothing is sent anywhere. Conversion runs on the phone. There is no upload and no server. Browse Rboard is the exception to “no server”: it downloads from GitHub, and sends nothing about you.

WM Keyboard reads these formats from their published descriptions. No code from either project is used: FlorisBoard is Apache-2.0 and HeliBoard is GPL-3.0, while WM Keyboard is MIT.

The .cin, Rime and m17n readers, and the m17n rule engine, were written from those formats’ documentation and from what their published files do. No code from gcin, OpenVanilla, librime or m17n-lib is used, and no table or rule file ships with the app. A table you import keeps its own licence: many .cin and Rime tables are free to share, and some, such as Boshiamy’s, are for personal use only.

Gboard’s theme format has no published description, so its reader was written from the themes in the Rboard repository rather than from any Gboard or Rboard code. Rboard themes state no licence. A theme you import stays the work of whoever made it, and a pack’s author is named on the dialog; ask before you publish one.

A .flex records its author and its licence, and the confirm dialog reads both out when you open one from a file manager. A theme here has no field to hold them in, so that dialog is where they stop. Write them down while they are in front of you. If you publish a converted theme in an add-on repository, keep them with it.