When I first started programming seriously in 2015, I quickly came to the conclusion that the Swiss German keyboard layout was inadequate for programming. When programming, you use a lot of characters like those: {}/\|&~\`@^#. And while all of them are accessible on a Swiss German keyboard layout, for some of them you need strange keyboard combinations like Alt Gr + n, Alt Gr + G or Alt + Shift + 5.
Until 2018, I just accepted my fate. At least once a week I would search for a tilde or a backslash. In 2018, I got a new job, and with it came a new MacBook. In my ignorance, up to this point I had always stuck to Windows. Now I was forced to learn a new operating system, and because that meant learning new keyboard shortcuts anyway, I decided to finally solve my Swiss German keyboard woes by also switching to the superior US keyboard layout, where all the symbols I needed every day while programming would be much more accessible.
So I switched to the US layout and immediately ran into a new problem: There are no umlauts on the US layout. Ya know, those fuckers: äöü. I could live with the Y / Z switch and I was also less worried about letters like é, è and à, because despite some of my school teachers best efforts, I had not turned French yet. But the umlauts are an integral part of German and Swiss German communication. I needed them.
Luckily, on macOS you can define a keyboard shortcut to switch between keyboard layouts, and to my amazement, macOS does not randomly add 5 more unwanted, unnecessary keyboard layouts every time you update the operating system. So I did that, and this solved about 90% of my problems. And yet, some remained.
This post is about those remaining problems and how I solved them all, finally.
The problem with the Y and the Z on my two keyboard layouts wasn't that either of them was wrong. The problem was that they were different. I started switching keyboard layouts a lot. Like, hundreds or thousands of times a day. Every time I would switch to a communication app, I'd switch the keyboard layout to Swiss German. And every time I would switch back to the code, I'd switch the keyboard layout back to US English.
That's the theory anyway. In practice, I would switch to a communication app or code, start writing, write happily until I hit a word containing Y or Z, notice that the wrong character appeared, get pissed, hit backspace, switch the keyboard layout and type again.
I eventually resorted to using Karabiner Elements for this. This fantastic app lets you remap keys to different keys, and do this based on conditions.
After a bit of tinkering, I ended up with this "Complex Modification":
{
"description": "Switch Z and Y on German keyboards",
"manipulators": [
{
"conditions": [
{
"input_sources": [{ "language": "^de$" }],
"type": "input_source_if"
}
],
"from": {
"key_code": "z",
"modifiers": { "optional": ["any"] }
},
"to": [{ "key_code": "y" }],
"type": "basic"
},
{
"conditions": [
{
"input_sources": [{ "language": "^de$" }],
"type": "input_source_if"
}
],
"from": {
"key_code": "y",
"modifiers": { "optional": ["any"] }
},
"to": [{ "key_code": "z" }],
"type": "basic"
}
]
}
This switches Y to Z and Z to Y, but only on the Swiss German keyboard layout. Great, problem solved.
I also use Karabiner Elements to switch several other keys around, for example I switch Fn and Ctrl, have Backspace where you would assume CapsLock and Enter on Right Command. Karabiner Elements lets you configure this stuff per device too, which is amazing.


Switching the keyboard layout all the time became tiresome very quickly, and I searched for a solution to this many times, always without luck, until recently, when I found an app called Input Source Pro. This app is free and solves exactly my problem. With it, you can define keyboard layouts for applications. If you switch to that application, your chosen keyboard layout is automatically selected. No need to manually switch.
You can also set rules for specific websites, meaning that I could set my email client, WhatsApp and other German context websites to use the Swiss German keyboard layout, whereas the rest would use the US layout. This worked without issue together with my Y / Z rule from Karabiner Elements.
Since the dawn of time, I have Command + ` set as the keyboard shortcut for switching between windows of the same application (I think that's the macOS default). This is different from Command + Tab, which switched between applications. The ` key, on the US layout, is right above the Tab key, so this is perfect. I use both all of the time. It's the main way I navigate my computer, and having those keys right on top of each other is perfect.
The problem has always been that this shortcut only works on the US keyboard. Because the key above the Tab key on the Swiss German keyboard layout is not `, but >. ` on the Swiss German layout is where + is on the US layout: Shift + the key next to backspace (=, or ^ on the Swiss German Layout).
Hold on, you might say, this is the same problem as the Y and Z problem above, no? Map them to each other, problem solved.
Unfortunately, it's not that simple. See, while Command + ` goes to the next window of the same application. Command + Shift + ` goes to the previous window of the same application. So while I could, on the Swiss German keyboard layout, map > to Shift + ^ using Karabiner Elements, that keyboard combination mapped to includes a Shift. And that Shift is handed to macOS, and macOS happily switches to the previous window of the same application, instead of the next one.
So, for a long time I just let it be. I would write someone in German, switch back to my browser with Command + Tab. After a while I'd want to switch to a different browser window, hit Command + `, notice that nothing happened because the Swiss German keyboard layout was selected, get pissed, switch the keyboard layout, hit Command + ` again.
But then I started using Input Switcher Pro (as described above), and this problem got much worse. Because now, every time I switched to a browser tab with, for example, my email client, the Swiss German keyboard layout would be selected. If I rotated through a couple browser windows using Command + `, this would work until I hit my email client, where I got stuck because now the keyboard layout was, as intended, Swiss German.
So now I absolutely had to solve this problem.
Once again, Karabiner Elements finally did the trick. The Shift key was the problem. So what I had to do were three steps:
- In the macOS system settings, map the keyboard shortcut to rotate windows of the same application to something that did not involve Shift (or ideally any other modifier key) on either the Swiss German keyboard layout or the US one. I find it quite funny that there is exactly one key that is not a letter, number or space (which are all commonly used by keyboard shortcuts of the operating system and applications) and matches this description:
'(quote). You can create a'on both keyboard layouts with a single key. So I mapped the shortcut toCommand + ' - Map
`to'on the US keyboard layout - Map
`to-on the Swiss German keyboard layout. Why-and not'? Because-on the Swiss German keyboard layout is where ' would be, if it were the US keyboard layout. But then why`and not>? Because > is where`is on the US keyboard layout, and so we don't have to "translate" it. As far as Karabiner Elements is concerned, if I hit>on the Swiss German keyboard layout,`was pressed (macOS has a different opinion on the matter, which is why we're here).
For Step 1, here's a screenshot:


For steps 2 and 3, here's the "Complex Modifications" I used in Karabiner Elements:
{
"description": "Switch Z and Y on German keyboards",
"manipulators": [
{
"conditions": [
{
"input_sources": [{ "language": "^de$" }],
"type": "input_source_if"
}
],
"from": {
"key_code": "grave_accent_and_tilde",
"modifiers": {
"mandatory": ["left_command"],
"optional": ["any"]
}
},
"to": [
{
"key_code": "hyphen",
"modifiers": ["left_command"]
}
],
"type": "basic"
},
{
"conditions": [
{
"input_sources": [{ "language": "^en$" }],
"type": "input_source_if"
}
],
"from": {
"key_code": "grave_accent_and_tilde",
"modifiers": {
"mandatory": ["left_command"],
"optional": ["any"]
}
},
"to": [
{
"key_code": "quote",
"modifiers": ["left_command"]
}
],
"type": "basic"
}
]
}
So now if I hit Command + [the key above Tab on the US keyboard layout], that key (`), will be translated to ' by Karabiner Elements, which then runs the next window of application shortcut.
For the Swiss German keyboard layout > gets interpreted as `, which then translates to -, which gets interpreted as ', which then runs the shortcut. Yes, really. And best of all, this does not affect ' or any other symbol I type on either keyboard.
No Shift involved. Problem solved. Not complicated at all.
With all of this setup in place, I had a couple small problems remaining.
Somehow, my new setup fucked up the shortcut bindings in IntelliJ IDEs. Luckily, it's very simple to redefine them by going to Settings > Keymap and then setting the "Next Project Window" and "Previous Project Window" shortcuts respectively.


With all of this setup in place, I had one problem remaining. I use Figma all the time in my work. And Figma is the only app or website that I have come across that uses the Command + ' shortcut. It's used to show or hide the pixel grid, which is a functionality that can be useful, I guess, but I do not need that shortcut.
Unfortunately, Figma does not allow me to change or disable that shortcut, so, once more, I had to resort to an external tool. TamperMonkey this time, a browser extension that allows you to modify the contents and the behavior of any website, as it is displayed to you personally.
I love TamperMonkey and I use it for everything from automatically closing cookie banners to automatically decline Google consent screens to hiding ads my ad blocker doesn't catch. And now, for disabling a keyboard shortcut in Figma too.
This is the UserScript for TamperMonkey I came up with:
// ==UserScript==
// @name Figma
// @match https://www.figma.com/*
// @grant none
// ==/UserScript==
(() => {
'use strict';
document.addEventListener('keydown', (event) => {
if (event.metaKey && event.key === '\'') {
event.cancelBubble = true;
event.stopImmediatePropagation();
event.stopPropagation();
return;
}
}, true)
})();
And this, after 11 years, finally solved the last of my keyboard layout issues. At least on macOS. Fuck Windows.