I want to write simple bash script which translates input between different keyboard layout. For example, if my system has Russian and English layouts, and I'm passing 'Руддщ' string to this script, it should output 'Hello'.

Currently I'm using this code:

echo "$@" | iconv -t cp1251 | tr $(echo "[йцукенгшщзхъфывапролджэ\\ячсмитьбю.ЙЦУКЕНГШЩЗХЪФЫВАПРОЛДЖЭ/ЯЧСМИТЬБЮ,\"№;:?Ёё]" | iconv -t cp1251) "[qwertyuiop\[\]asdfghjkl;'\\zxcvbnm,./QWERTYUIOP{}ASDFGHJKL:\"|ZXCVBNM<>?@#$^&~\`]"

There are obvious disadvantages:

  • I have to use iconv, because my system uses utf8 and tr can't use it.
  • I have to type all characters manually, which leads to lack of applicability and high error possibility.

I know xneur has simillar functionality, but I don't want to switch layout on the fly, just translate strings on request. I've looked through xneur source code, but haven't found anything useful.

2 Answers 2


I guess some library for this exists (if only internally at Google?). For example, https://www.google.com/search?q=hjccbz correctly displays results for россия. It doesn't work for ghbdtn, though (perhaps because misspelling привет like this is a common in-joke?)

In fact, searching for these strings brings up some half-promising hits, though nothing clearly directly applicable.

Anyway, there is no reason you couldn't put your own code in a script, which obviously removes the need for retyping this correctly.

If you save this with a CP1251 encoding from your editor, you can avoid the nested iconv:

iconv -t cp1251 |
tr 'йцукенгшщзхъфывапролджэ\ячсмитьбю.ЙЦУКЕНГШЩЗХЪФЫВАПРОЛДЖЭ/ЯЧСМИТЬБЮ,"№;:?Ёё' "qwertyuiop[]asdfghjkl;'\\zxcvbnm,./QWERTYUIOP{}ASDFGHJKL:\"|ZXCVBNM<>?@#$^&~\`"

I think you had a false assumption about needing to use square brackets around the arguments to tr which I also attempted to fix.

Save to a location in your PATH with a memorable and easy to type name, chmod +x, and there you have it.

  • The Google transliteration examples are obviously in the opposite direction. I don't have a Cyrillic keyboard so it's hard to test if they do this both ways (getting this far was already a challenge with only my phone to test on) but I'd guess they do.
    – tripleee
    Apr 22, 2017 at 9:39
  • 1
    tr from the latest release of GNU coreutils does not support UTF-8. You can run it in a UTF-8 locale, and you can pass it arguments outside the ASCII range, but it'll still operate on bytes, not characters, so it won't translate non-ASCII characters correctly. Apr 22, 2017 at 22:14
  • Thanks for your improvement to my code, it's definetely better this way. But I still beleive there is some better solution which I'm missing, so not closing the question yet. Apr 24, 2017 at 4:35

I don’t imagine this is possible since, with a give layout, there can be several ways to type the same character. For example, with my french layout, I can type “É” either either by enabling CapsLock and typing é, or by Compose-'-Shift-e.

  • Why is that a problem? Just define two mappings to the same output. You can't get 100% reliable round-trip translation back to the original input but that should not matter at all for this particular use case.
    – tripleee
    Apr 22, 2017 at 9:35
  • 1
    @tripleee It is a problem because the different ways to type one character with keyboard layout 1 might result in different characters in keyboard layout 2. The basic US layout has no redundancy, but many others do. For example, with a French keyboard, é is what is 2 on a Russian keyboard, whereas Compose+'+e is Compose+э+у — granted that one doesn't do anything, but there might be others that do. Apr 22, 2017 at 22:10
  • Of course, if there are multiple ways to type a on a keyboard, and they correspond to different characters in the destination mapping, you can't know which one to choose. But can you give a practical example for the scenario at hand? The fact that the OP has a basically working solution should already convince you that the problem is practically solvable for the case of Russian cyrillics to US English alphabetics.
    – tripleee
    Apr 23, 2017 at 8:41
  • And even if there are some ambiguities, many can be resolved by context. If a could be typed two ways, you can still in practice guess whether "alphabet" or "blphbbet" is correct with a bit of character trigram statistics or (in the worst case) brute force a lot of the time.
    – tripleee
    Apr 23, 2017 at 8:46
  • 1
    @tripleee It might work for “textual” inputs, although using trigram statistics is significantly more complicated than a transliteration. But it might not work for more “random-like” inputs, such as password inputs. So I guess all depends what the OP intends to do… Apr 24, 2017 at 0:01

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.