How to create a custom keyboard layout in Ubuntu 11.04
I’m not pretending to be a specialist in this field. Custom keyboard layouts may contain lots of features like ligatures, auto-replaces of diacritic signs, support for right-to-left input. But here I’ll just explain how to create simple 3-layer layout (3-layer means that we can modify keys not only with Shift, but with other button too, usually it’s AltGr or right Alt).
Once I met Ilya Birman’s layout and fell in love with it till the moment I understood I’m not really comfortable with it. There were two major reasons: sometimes I write in german, so I need umlauts (ä, ö, ü) and eszett (ß), and old cyrillic symbols (ѣ, ѵ, ѳ) seemed to me to be placed not logically. So that time I made a Windows layout for myself, and now I show how to create it in the Ubuntu.
Keyboard layout files we need stored in /usr/share/X11/xkb/. Layouts are placed in the folder symbols. And in addition we need two register files: rules/base.xml and rules/endev.xml.
At first we want to create layout. Create a new file in symbols/, for example new_en. Then we place this code in it:
partial alphanumeric_keys
xkb_symbols "newen" {
name[Group1]="Latin layout with German letters";
key <TLDE> {[ U0060, U007E, U00B4, U0300 ]}; // ~
key <AE01> {[ U0031, U0021, U00B9, U00B9 ]}; // 1
key <AE02> {[ U0032, U0040, U00B2, U00BD ]}; // 2
key <AE03> {[ U0033, U0023, U00B3, U2153 ]}; // 3
key <AE04> {[ U0034, U0024, U0024, U00BC ]}; // 4
key <AE05> {[ U0035, U0025, U2030, U2030 ]}; // 5
key <AE06> {[ U0036, U005E, U2191, U0302 ]}; // 6
key <AE07> {[ U0037, U0026, U0037, U0037 ]}; // 7
key <AE08> {[ U0038, U002A, U221E, U221E ]}; // 8
key <AE09> {[ U0039, U0028, U2190, U2190 ]}; // 9
key <AE10> {[ U0030, U0029, U2192, U2192 ]}; // 0
key <AE11> {[ U002D, U005F, U2014, U2013 ]}; // -
key <AE12> {[ U003D, U002B, U2260, U00B1 ]}; // +
key <AD01> {[ U0071, U0051, U0071, U0306 ]}; // q
key <AD02> {[ U0077, U0057, U0077, U0077 ]}; // w
key <AD03> {[ U0065, U0045, U20AC, U20AC ]}; // e
key <AD04> {[ U0072, U0052, U00AE, U00AE ]}; // r
key <AD05> {[ U0074, U0054, U2122, U2122 ]}; // t
key <AD06> {[ U0079, U0059, U0079, U0059 ]}; // y
key <AD07> {[ U0075, U0055, U00FC, U00DC ]}; // u
key <AD08> {[ U0069, U0049, U0069, U0049 ]}; // i
key <AD09> {[ U006F, U004F, U00F6, U00D6 ]}; // o
key <AD10> {[ U0070, U0050, U0027, U0022 ]}; // p
key <AD11> {[ U005B, U007B, U005B, U007B ]}; // [
key <AD12> {[ U005D, U007D, U005D, U007D ]}; // ]
key <BKSL> {[ U005C, U007C, U005C, U005C ]}; // \
key <AC01> {[ U0061, U0041, U00E4, U00C4 ]}; // a
key <AC02> {[ U0073, U0053, U00DF, U00A7 ]}; // s
key <AC03> {[ U0064, U0044, U00B0, U00B0 ]}; // d
key <AC04> {[ U0066, U0046, U00A3, U00A3 ]}; // f
key <AC05> {[ U0067, U0047, U0067, U0067 ]}; // g
key <AC06> {[ U0068, U0048, U0068, U0068 ]}; // h
key <AC07> {[ U006A, U004A, U201E, U201E ]}; // j
key <AC08> {[ U006B, U004B, U201C, U2018 ]}; // k
key <AC09> {[ U006C, U004C, U201D, U2019 ]}; // l
key <AC10> {[ U003B, U003A, U2018, U0308 ]}; // ;
key <AC11> {[ U0027, U0022, U2019, U2019 ]}; // '
key <AB01> {[ U007A, U005A, U2248, U2318 ]}; // z
key <AB02> {[ U0078, U0058, U00D7, U22C5 ]}; // x
key <AB03> {[ U0063, U0043, U00A9, U00A2 ]}; // c
key <AB04> {[ U0076, U0056, U2193, U030C ]}; // v
key <AB05> {[ U0062, U0042, U0062, U0062 ]}; // b
key <AB06> {[ U006E, U004E, U006E, U0303 ]}; // n
key <AB07> {[ U006D, U004D, U2212, U2212 ]}; // m
key <AB08> {[ U002C, U003C, U00AB, U201E ]}; // ,
key <AB09> {[ U002E, U003E, U00BB, U201C ]}; // .
key <AB10> {[ U002F, U003F, U002F, U0301 ]}; // /
key <SPCE> {[ U0020, U0020, U00A0, U00A0 ]}; // space
include "level3(ralt_switch)"
};
The first code in each array is just the normal keydown, the second Shift+Key, the next AltGr+Key and the last AltGr+Shift+Key. It looks like this.

The last commented string is for setting the right Alt as a modifying key for 3rd level. This is optional as you can bind the key you need while adding this layout in keyboard settings. I used codes for symbols, though it’s recommended to use names, because I’m not sure whether they work for Cyrillic layout. Cyrillic file new_ru:
partial alphanumeric_keys
xkb_symbols "newru" {
name[Group1]="Cyrillic layout with old letters";
key <TLDE> {[ U0451, U0401, U00B4, U0300 ]}; // ~
key <AE01> {[ U0031, U0021, U00B9, U00B9 ]}; // 1
key <AE02> {[ U0032, U0022, U00B2, U00BD ]}; // 2
key <AE03> {[ U0033, U2116, U00B3, U2153 ]}; // 3
key <AE04> {[ U0034, U003B, U0024, U00BC ]}; // 4
key <AE05> {[ U0035, U0025, U2030, U2030 ]}; // 5
key <AE06> {[ U0036, U003A, U2191, U0302 ]}; // 6
key <AE07> {[ U0037, U003F, U0037, U0037 ]}; // 7
key <AE08> {[ U0038, U002A, U221E, U221E ]}; // 8
key <AE09> {[ U0039, U0028, U2190, U2190 ]}; // 9
key <AE10> {[ U0030, U0029, U2192, U2192 ]}; // 0
key <AE11> {[ U002D, U005F, U2014, U2013 ]}; // -
key <AE12> {[ U003D, U002B, U2260, U00B1 ]}; // +
key <AD01> {[ U0439, U0419, U0439, U0306 ]}; // q
key <AD02> {[ U0446, U0426, U0446, U0446 ]}; // w
key <AD03> {[ U0443, U0423, U20AC, U20AC ]}; // e
key <AD04> {[ U043A, U041A, U00AE, U2122 ]}; // r
key <AD05> {[ U0435, U0415, U0463, U0462 ]}; // t
key <AD06> {[ U043D, U041D, U043D, U041D ]}; // y
key <AD07> {[ U0433, U0413, U0433, U0413 ]}; // u
key <AD08> {[ U0448, U0428, U0456, U0406 ]}; // i
key <AD09> {[ U0449, U0429, U0449, U0429 ]}; // o
key <AD10> {[ U0437, U0417, U0027, U0022 ]}; // p
key <AD11> {[ U0445, U0425, U005B, U007B ]}; // [
key <AD12> {[ U044A, U042A, U005D, U007D ]}; // ]
key <BKSL> {[ U005C, U002F, U005C, U005C ]}; // \
key <AC01> {[ U0444, U0424, U0473, U0472 ]}; // a
key <AC02> {[ U044B, U042B, U00A7, U00A7 ]}; // s
key <AC03> {[ U0432, U0412, U00B0, U00B0 ]}; // d
key <AC04> {[ U0430, U0410, U00A3, U00A3 ]}; // f
key <AC05> {[ U043F, U041F, U043F, U043F ]}; // g
key <AC06> {[ U0440, U0420, U0440, U0440 ]}; // h
key <AC07> {[ U043E, U041E, U201E, U201E ]}; // j
key <AC08> {[ U043B, U041B, U201C, U2018 ]}; // k
key <AC09> {[ U0434, U0414, U201D, U2019 ]}; // l
key <AC10> {[ U0436, U0416, U2018, U0308 ]}; // ;
key <AC11> {[ U044D, U042D, U2019, U2019 ]}; // '
key <AB01> {[ U044F, U042F, U2248, U2318 ]}; // z
key <AB02> {[ U0447, U0427, U00D7, U22C5 ]}; // x
key <AB03> {[ U0441, U0421, U00A9, U00A2 ]}; // c
key <AB04> {[ U043C, U041C, U2193, U030C ]}; // v
key <AB05> {[ U0438, U0418, U0475, U0474 ]}; // b
key <AB06> {[ U0442, U0422, U0442, U0303 ]}; // n
key <AB07> {[ U044C, U042C, U2212, U2212 ]}; // m
key <AB08> {[ U0431, U0411, U00AB, U201E ]}; // ,
key <AB09> {[ U044E, U042E, U00BB, U201C ]}; // .
key <AB10> {[ U002E, U002C, U002E, U0301 ]}; // /
key <SPCE> {[ U0020, U0020, U00A0, U00A0 ]}; // space
// include "level3(ralt_switch)"
};
This layout looks like this.

The difference with Birman’s layout is that old letters are on better places (of course from my point of view).
Now we need to register this layout in both xml files. We should insert a new <layout> tag between existed layouts:
...
</layout>
<layout>
<configItem>
<name>new_en</name>
<shortDescription>Lat</shortDescription>
<description>Latin layout</description>
<languageList>
<iso639Id>eng</iso639Id>
</languageList>
</configItem>
<variantList>
<variant>
<configItem>
<name>newen</name>
<description>with German letters</description>
</configItem>
</variant>
</variantList>
</layout>
<layout>
...
The new_en here is the name of our file, Lat is how our layout will be named in the tray, the description of our layout will be “Latin layout with German letters”, eng is the name of the language where to look for our layout, and newen is how we called our partial layout in the file.
If we want to install cyrillic layout too, we should insert the similar text for it again in both of the files: rules/base.xml and rules/endev.xml.
That’s it! Now we can go to keyboard settings, find our layouts and use them immediately.
Still there’re two notes: if you used non-latin symbols in description they may not be displayed until reboot. If you deleted the default layout (for example, us) and after reboot it appeared again, you should turn off auto-login and choose right layout in the login window, after that ubuntu should remember your settings.