summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--data/constants/keycodes/extras/keycodes_uk_0.0.1.hjson353
-rw-r--r--data/constants/keycodes/extras/keycodes_us_0.0.1.hjson155
-rwxr-xr-xlib/python/qmk/cli/generate/api.py9
-rw-r--r--lib/python/qmk/cli/generate/keycodes.py54
-rw-r--r--lib/python/qmk/keycodes.py73
-rw-r--r--quantum/keymap_extras/keymap_uk.h96
-rw-r--r--quantum/keymap_extras/keymap_us.h75
7 files changed, 690 insertions, 125 deletions
diff --git a/data/constants/keycodes/extras/keycodes_uk_0.0.1.hjson b/data/constants/keycodes/extras/keycodes_uk_0.0.1.hjson
new file mode 100644
index 0000000000..006bf5c59e
--- /dev/null
+++ b/data/constants/keycodes/extras/keycodes_uk_0.0.1.hjson
@@ -0,0 +1,353 @@
+{
+    "aliases": {
+/*
+ * ┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───────┐
+ * │ ` │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │ 8 │ 9 │ 0 │ - │ = │       │
+ * ├───┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─────┤
+ * │     │ Q │ W │ E │ R │ T │ Y │ U │ I │ O │ P │ [ │ ] │     │
+ * ├─────┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┐    │
+ * │      │ A │ S │ D │ F │ G │ H │ J │ K │ L │ ; │ ' │ # │    │
+ * ├────┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴───┴────┤
+ * │    │ \ │ Z │ X │ C │ V │ B │ N │ M │ , │ . │ / │          │
+ * ├────┼───┴┬──┴─┬─┴───┴───┴───┴───┴───┴──┬┴───┼───┴┬────┬────┤
+ * │    │    │    │                        │    │    │    │    │
+ * └────┴────┴────┴────────────────────────┴────┴────┴────┴────┘
+ */
+        "KC_GRV": {
+            "key": "UK_GRV",
+            "label": "`"
+        },
+        "KC_1": {
+            "key": "UK_1",
+            "label": "1"
+        },
+        "KC_2": {
+            "key": "UK_2",
+            "label": "2"
+        },
+        "KC_3": {
+            "key": "UK_3",
+            "label": "3"
+        },
+        "KC_4": {
+            "key": "UK_4",
+            "label": "4"
+        },
+        "KC_5": {
+            "key": "UK_5",
+            "label": "5"
+        },
+        "KC_6": {
+            "key": "UK_6",
+            "label": "6"
+        },
+        "KC_7": {
+            "key": "UK_7",
+            "label": "7"
+        },
+        "KC_8": {
+            "key": "UK_8",
+            "label": "8"
+        },
+        "KC_9": {
+            "key": "UK_9",
+            "label": "9"
+        },
+        "KC_0": {
+            "key": "UK_0",
+            "label": "0"
+        },
+        "KC_MINS": {
+            "key": "UK_MINS",
+            "label": "-"
+        },
+        "KC_EQL": {
+            "key": "UK_EQL",
+            "label": "="
+        },
+        "KC_Q": {
+            "key": "UK_Q",
+            "label": "Q"
+        },
+        "KC_W": {
+            "key": "UK_W",
+            "label": "W"
+        },
+        "KC_E": {
+            "key": "UK_E",
+            "label": "E"
+        },
+        "KC_R": {
+            "key": "UK_R",
+            "label": "R"
+        },
+        "KC_T": {
+            "key": "UK_T",
+            "label": "T"
+        },
+        "KC_Y": {
+            "key": "UK_Y",
+            "label": "Y"
+        },
+        "KC_U": {
+            "key": "UK_U",
+            "label": "U"
+        },
+        "KC_I": {
+            "key": "UK_I",
+            "label": "I"
+        },
+        "KC_O": {
+            "key": "UK_O",
+            "label": "O"
+        },
+        "KC_P": {
+            "key": "UK_P",
+            "label": "P"
+        },
+        "KC_LBRC": {
+            "key": "UK_LBRC",
+            "label": "["
+        },
+        "KC_RBRC": {
+            "key": "UK_RBRC",
+            "label": "]"
+        },
+        "KC_A": {
+            "key": "UK_A",
+            "label": "A"
+        },
+        "KC_S": {
+            "key": "UK_S",
+            "label": "S"
+        },
+        "KC_D": {
+            "key": "UK_D",
+            "label": "D"
+        },
+        "KC_F": {
+            "key": "UK_F",
+            "label": "F"
+        },
+        "KC_G": {
+            "key": "UK_G",
+            "label": "G"
+        },
+        "KC_H": {
+            "key": "UK_H",
+            "label": "H"
+        },
+        "KC_J": {
+            "key": "UK_J",
+            "label": "J"
+        },
+        "KC_K": {
+            "key": "UK_K",
+            "label": "K"
+        },
+        "KC_L": {
+            "key": "UK_L",
+            "label": "L"
+        },
+        "KC_SCLN": {
+            "key": "UK_SCLN",
+            "label": ";"
+        },
+        "KC_QUOT": {
+            "key": "UK_QUOT",
+            "label": "'"
+        },
+        "KC_NUHS": {
+            "key": "UK_HASH",
+            "label": "#"
+        },
+        "KC_NUBS": {
+            "key": "UK_BSLS",
+            "label": "\\"
+        },
+        "KC_Z": {
+            "key": "UK_Z",
+            "label": "Z"
+        },
+        "KC_X": {
+            "key": "UK_X",
+            "label": "X"
+        },
+        "KC_C": {
+            "key": "UK_C",
+            "label": "C"
+        },
+        "KC_V": {
+            "key": "UK_V",
+            "label": "V"
+        },
+        "KC_B": {
+            "key": "UK_B",
+            "label": "B"
+        },
+        "KC_N": {
+            "key": "UK_N",
+            "label": "N"
+        },
+        "KC_M": {
+            "key": "UK_M",
+            "label": "M"
+        },
+        "KC_COMM": {
+            "key": "UK_COMM",
+            "label": ","
+        },
+        "KC_DOT": {
+            "key": "UK_DOT",
+            "label": "."
+        },
+        "KC_SLSH": {
+            "key": "UK_SLSH",
+            "label": "/"
+        },
+
+/* Shifted symbols
+ * ┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───────┐
+ * │ ¬ │ ! │ " │ £ │ $ │ % │ ^ │ & │ * │ ( │ ) │ _ │ + │       │
+ * ├───┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─────┤
+ * │     │   │   │   │   │   │   │   │   │   │   │ { │ } │     │
+ * ├─────┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┐    │
+ * │      │   │   │   │   │   │   │   │   │   │ : │ @ │ ~ │    │
+ * ├────┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴───┴────┤
+ * │    │ | │   │   │   │   │   │   │   │ < │ > │ ? │          │
+ * ├────┼───┴┬──┴─┬─┴───┴───┴───┴───┴───┴──┬┴───┼───┴┬────┬────┤
+ * │    │    │    │                        │    │    │    │    │
+ * └────┴────┴────┴────────────────────────┴────┴────┴────┴────┘
+ */
+        "S(UK_GRV)": {
+            "key": "UK_NOT",
+            "label": "¬"
+        },
+        "S(UK_1)": {
+            "key": "UK_EXLM",
+            "label": "!"
+        },
+        "S(UK_2)": {
+            "key": "UK_DQUO",
+            "label": "\""
+        },
+        "S(UK_3)": {
+            "key": "UK_PND",
+            "label": "£"
+        },
+        "S(UK_4)": {
+            "key": "UK_DLR",
+            "label": "$"
+        },
+        "S(UK_5)": {
+            "key": "UK_PERC",
+            "label": "%"
+        },
+        "S(UK_6)": {
+            "key": "UK_CIRC",
+            "label": "^"
+        },
+        "S(UK_7)": {
+            "key": "UK_AMPR",
+            "label": "&"
+        },
+        "S(UK_8)": {
+            "key": "UK_ASTR",
+            "label": "*"
+        },
+        "S(UK_9)": {
+            "key": "UK_LPRN",
+            "label": "("
+        },
+        "S(UK_0)": {
+            "key": "UK_RPRN",
+            "label": ")"
+        },
+        "S(UK_MINS)": {
+            "key": "UK_UNDS",
+            "label": "_"
+        },
+        "S(UK_EQL)": {
+            "key": "UK_PLUS",
+            "label": "+"
+        },
+        "S(UK_LBRC)": {
+            "key": "UK_LCBR",
+            "label": "{"
+        },
+        "S(UK_RBRC)": {
+            "key": "UK_RCBR",
+            "label": "}"
+        },
+        "S(UK_SCLN)": {
+            "key": "UK_COLN",
+            "label": ":"
+        },
+        "S(UK_QUOT)": {
+            "key": "UK_AT",
+            "label": "@"
+        },
+        "S(UK_HASH)": {
+            "key": "UK_TILD",
+            "label": "~"
+        },
+        "S(UK_BSLS)": {
+            "key": "UK_PIPE",
+            "label": "|"
+        },
+        "S(UK_COMM)": {
+            "key": "UK_LABK",
+            "label": "<"
+        },
+        "S(UK_DOT)": {
+            "key": "UK_RABK",
+            "label": ">"
+        },
+        "S(UK_SLSH)": {
+            "key": "UK_QUES",
+            "label": "?"
+        },
+
+/* AltGr symbols
+ * ┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───────┐
+ * │ ¦ │   │   │   │ € │   │   │   │   │   │   │   │   │       │
+ * ├───┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─────┤
+ * │     │   │   │ É │   │   │   │ Ú │ Í │ Ó │   │   │   │     │
+ * ├─────┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┐    │
+ * │      │ Á │   │   │   │   │   │   │   │   │   │   │   │    │
+ * ├────┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴───┴────┤
+ * │    │   │   │   │   │   │   │   │   │   │   │   │          │
+ * ├────┼───┴┬──┴─┬─┴───┴───┴───┴───┴───┴──┬┴───┼───┴┬────┬────┤
+ * │    │    │    │                        │    │    │    │    │
+ * └────┴────┴────┴────────────────────────┴────┴────┴────┴────┘
+ */
+        "ALGR(UK_GRV)": {
+            "key": "UK_BRKP",
+            "label": "¦"
+        },
+        "ALGR(UK_4)": {
+            "key": "UK_EURO",
+            "label": "€"
+        },
+        "ALGR(KC_E)": {
+            "key": "UK_EACU",
+            "label": "É"
+        },
+        "ALGR(KC_U)": {
+            "key": "UK_UACU",
+            "label": "Ú"
+        },
+        "ALGR(KC_I)": {
+            "key": "UK_IACU",
+            "label": "Í"
+        },
+        "ALGR(KC_O)": {
+            "key": "UK_OACU",
+            "label": "Ó"
+        },
+        "ALGR(KC_A)": {
+            "key": "UK_AACU",
+            "label": "Á"
+        }
+    }
+}
\ No newline at end of file
diff --git a/data/constants/keycodes/extras/keycodes_us_0.0.1.hjson b/data/constants/keycodes/extras/keycodes_us_0.0.1.hjson
new file mode 100644
index 0000000000..af7e462611
--- /dev/null
+++ b/data/constants/keycodes/extras/keycodes_us_0.0.1.hjson
@@ -0,0 +1,155 @@
+{
+    "aliases": {
+/* Shifted symbols
+ * ┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───────┐
+ * │ ~ │ ! │ @ │ # │ $ │ % │ ^ │ & │ * │ ( │ ) │ _ │ + │       │
+ * ├───┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─────┤
+ * │     │   │   │   │   │   │   │   │   │   │   │ { │ } │  |  │
+ * ├─────┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴─────┤
+ * │      │   │   │   │   │   │   │   │   │   │ : │ " │        │
+ * ├──────┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴────────┤
+ * │        │   │   │   │   │   │   │   │ < │ > │ ? │          │
+ * ├────┬───┴┬──┴─┬─┴───┴───┴───┴───┴───┴──┬┴───┼───┴┬────┬────┤
+ * │    │    │    │                        │    │    │    │    │
+ * └────┴────┴────┴────────────────────────┴────┴────┴────┴────┘
+ */
+        "S(KC_GRAVE)": {
+            "key": "KC_TILD",
+            "label": "~",
+            "aliases": [
+                "KC_TILDE"
+            ]
+        },
+        "S(KC_1)": {
+            "key": "KC_EXLM",
+            "label": "!",
+            "aliases": [
+                "KC_EXCLAIM"
+            ]
+        },
+        "S(KC_2)": {
+            "key": "KC_AT",
+            "label": "@"
+        },
+        "S(KC_3)": {
+            "key": "KC_HASH",
+            "label": "#"
+        },
+        "S(KC_4)": {
+            "key": "KC_DLR",
+            "label": "$",
+            "aliases": [
+                "KC_DOLLAR"
+            ]
+        },
+        "S(KC_5)": {
+            "key": "KC_PERC",
+            "label": "%",
+            "aliases": [
+                "KC_PERCENT"
+            ]
+        },
+        "S(KC_6)": {
+            "key": "KC_CIRC",
+            "label": "^",
+            "aliases": [
+                "KC_CIRCUMFLEX"
+            ]
+        },
+        "S(KC_7)": {
+            "key": "KC_AMPR",
+            "label": "&",
+            "aliases": [
+                "KC_AMPERSAND"
+            ]
+        },
+        "S(KC_8)": {
+            "key": "KC_ASTR",
+            "label": "*",
+            "aliases": [
+                "KC_ASTERISK"
+            ]
+        },
+        "S(KC_9)": {
+            "key": "KC_LPRN",
+            "label": "(",
+            "aliases": [
+                "KC_LEFT_PAREN"
+            ]
+        },
+        "S(KC_0)": {
+            "key": "KC_RPRN",
+            "label": ")",
+            "aliases": [
+                "KC_RIGHT_PAREN"
+            ]
+        },
+        "S(KC_MINUS)": {
+            "key": "KC_UNDS",
+            "label": "_",
+            "aliases": [
+                "KC_UNDERSCORE"
+            ]
+        },
+        "S(KC_EQUAL)": {
+            "key": "KC_PLUS",
+            "label": "+"
+        },
+        "S(KC_LEFT_BRACKET)": {
+            "key": "KC_LCBR",
+            "label": "{",
+            "aliases": [
+                "KC_LEFT_CURLY_BRACE"
+            ]
+        },
+        "S(KC_RIGHT_BRACKET)": {
+            "key": "KC_RCBR",
+            "label": "}",
+            "aliases": [
+                "KC_RIGHT_CURLY_BRACE"
+            ]
+        },
+        "S(KC_BACKSLASH)": {
+            "key": "KC_PIPE",
+            "label": "|"
+        },
+        "S(KC_SEMICOLON)": {
+            "key": "KC_COLN",
+            "label": ":",
+            "aliases": [
+                "KC_COLON"
+            ]
+        },
+        "S(KC_QUOTE)": {
+            "key": "KC_DQUO",
+            "label": "\"",
+            "aliases": [
+                "KC_DOUBLE_QUOTE",
+                "KC_DQT"
+            ]
+        },
+        "S(KC_COMMA)": {
+            "key": "KC_LABK",
+            "label": "<",
+            "aliases": [
+                "KC_LEFT_ANGLE_BRACKET",
+                "KC_LT"
+            ]
+        },
+        "S(KC_DOT)": {
+            "key": "KC_RABK",
+            "label": ">",
+            "aliases": [
+                "KC_RIGHT_ANGLE_BRACKET",
+                "KC_GT"
+            ]
+        },
+        "S(KC_SLASH)": {
+            "key": "KC_QUES",
+            "label": "?",
+            "aliases": [
+                "KC_QUESTION"
+            ]
+        }
+    }
+}
diff --git a/lib/python/qmk/cli/generate/api.py b/lib/python/qmk/cli/generate/api.py
index 8650a36b84..dd4830f543 100755
--- a/lib/python/qmk/cli/generate/api.py
+++ b/lib/python/qmk/cli/generate/api.py
@@ -11,7 +11,7 @@ from qmk.info import info_json
 from qmk.json_encoders import InfoJSONEncoder
 from qmk.json_schema import json_load
 from qmk.keyboard import find_readme, list_keyboards
-from qmk.keycodes import load_spec, list_versions
+from qmk.keycodes import load_spec, list_versions, list_languages
 
 DATA_PATH = Path('data')
 TEMPLATE_PATH = DATA_PATH / 'templates/api/'
@@ -44,6 +44,13 @@ def _resolve_keycode_specs(output_folder):
         output_file = output_folder / f'constants/keycodes_{version}.json'
         output_file.write_text(json.dumps(overall, indent=4), encoding='utf-8')
 
+    for lang in list_languages():
+        for version in list_versions(lang):
+            overall = load_spec(version, lang)
+
+            output_file = output_folder / f'constants/keycodes_{lang}_{version}.json'
+            output_file.write_text(json.dumps(overall, indent=4), encoding='utf-8')
+
     # Purge files consumed by 'load_spec'
     shutil.rmtree(output_folder / 'constants/keycodes/')
 
diff --git a/lib/python/qmk/cli/generate/keycodes.py b/lib/python/qmk/cli/generate/keycodes.py
index 29b7db3c80..cf80689708 100644
--- a/lib/python/qmk/cli/generate/keycodes.py
+++ b/lib/python/qmk/cli/generate/keycodes.py
@@ -8,6 +8,24 @@ from qmk.path import normpath
 from qmk.keycodes import load_spec
 
 
+def _render_key(key):
+    width = 7
+    if 'S(' in key:
+        width += len('S()')
+    if 'A(' in key:
+        width += len('A()')
+    if 'RCTL(' in key:
+        width += len('RCTL()')
+    if 'ALGR(' in key:
+        width += len('ALGR()')
+    return key.ljust(width)
+
+
+def _render_label(label):
+    label = label.replace("\\", "(backslash)")
+    return label
+
+
 def _generate_ranges(lines, keycodes):
     lines.append('')
     lines.append('enum qk_keycode_ranges {')
@@ -67,6 +85,22 @@ def _generate_helpers(lines, keycodes):
         lines.append(f'#define IS_{ group.upper() }_KEYCODE(code) ((code) >= {lo} && (code) <= {hi})')
 
 
+def _generate_aliases(lines, keycodes):
+    lines.append('')
+    lines.append('// Aliases')
+    for key, value in keycodes["aliases"].items():
+        define = _render_key(value.get("key"))
+        val = _render_key(key)
+        label = _render_label(value.get("label"))
+
+        lines.append(f'#define {define} {val} // {label}')
+
+    lines.append('')
+    for key, value in keycodes["aliases"].items():
+        for alias in value.get("aliases", []):
+            lines.append(f'#define {alias} {value.get("key")}')
+
+
 @cli.argument('-v', '--version', arg_only=True, required=True, help='Version of keycodes to generate.')
 @cli.argument('-o', '--output', arg_only=True, type=normpath, help='File to write to')
 @cli.argument('-q', '--quiet', arg_only=True, action='store_true', help="Quiet mode, only output error messages")
@@ -86,3 +120,23 @@ def generate_keycodes(cli):
 
     # Show the results
     dump_lines(cli.args.output, keycodes_h_lines, cli.args.quiet)
+
+
+@cli.argument('-v', '--version', arg_only=True, required=True, help='Version of keycodes to generate.')
+@cli.argument('-l', '--lang', arg_only=True, required=True, help='Language of keycodes to generate.')
+@cli.argument('-o', '--output', arg_only=True, type=normpath, help='File to write to')
+@cli.argument('-q', '--quiet', arg_only=True, action='store_true', help="Quiet mode, only output error messages")
+@cli.subcommand('Used by the make system to generate keymap_{lang}.h from keycodes_{lang}_{version}.json', hidden=True)
+def generate_keycode_extras(cli):
+    """Generates the header file.
+    """
+
+    # Build the header file.
+    keycodes_h_lines = [GPL2_HEADER_C_LIKE, GENERATED_HEADER_C_LIKE, '#pragma once', '#include "keymap.h"', '// clang-format off']
+
+    keycodes = load_spec(cli.args.version, cli.args.lang)
+
+    _generate_aliases(keycodes_h_lines, keycodes)
+
+    # Show the results
+    dump_lines(cli.args.output, keycodes_h_lines, cli.args.quiet)
diff --git a/lib/python/qmk/keycodes.py b/lib/python/qmk/keycodes.py
index cf1ee0767a..600163bab9 100644
--- a/lib/python/qmk/keycodes.py
+++ b/lib/python/qmk/keycodes.py
@@ -2,7 +2,42 @@ from pathlib import Path
 
 from qmk.json_schema import deep_update, json_load, validate
 
-CONSTANTS_PATH = Path('data/constants/keycodes/')
+CONSTANTS_PATH = Path('data/constants/')
+KEYCODES_PATH = CONSTANTS_PATH / 'keycodes'
+EXTRAS_PATH = KEYCODES_PATH / 'extras'
+
+
+def _find_versions(path, prefix):
+    ret = []
+    for file in path.glob(f'{prefix}_[0-9].[0-9].[0-9].hjson'):
+        ret.append(file.stem.split('_')[-1])
+
+    ret.sort(reverse=True)
+    return ret
+
+
+def _load_fragments(path, prefix, version):
+    file = path / f'{prefix}_{version}.hjson'
+    if not file.exists():
+        raise ValueError(f'Requested keycode spec ({prefix}:{version}) is invalid!')
+
+    # Load base
+    spec = json_load(file)
+
+    # Merge in fragments
+    fragments = path.glob(f'{prefix}_{version}_*.hjson')
+    for file in fragments:
+        deep_update(spec, json_load(file))
+
+    return spec
+
+
+def _search_path(lang=None):
+    return EXTRAS_PATH if lang else KEYCODES_PATH
+
+
+def _search_prefix(lang=None):
+    return f'keycodes_{lang}' if lang else 'keycodes'
 
 
 def _validate(spec):
@@ -19,26 +54,20 @@ def _validate(spec):
         raise ValueError(f'Keycode spec contains duplicate keycodes! ({",".join(duplicates)})')
 
 
-def load_spec(version):
+def load_spec(version, lang=None):
     """Build keycode data from the requested spec file
     """
     if version == 'latest':
-        version = list_versions()[0]
+        version = list_versions(lang)[0]
 
-    file = CONSTANTS_PATH / f'keycodes_{version}.hjson'
-    if not file.exists():
-        raise ValueError(f'Requested keycode spec ({version}) is invalid!')
+    path = _search_path(lang)
+    prefix = _search_prefix(lang)
 
     # Load base
-    spec = json_load(file)
-
-    # Merge in fragments
-    fragments = CONSTANTS_PATH.glob(f'keycodes_{version}_*.hjson')
-    for file in fragments:
-        deep_update(spec, json_load(file))
+    spec = _load_fragments(path, prefix, version)
 
     # Sort?
-    spec['keycodes'] = dict(sorted(spec['keycodes'].items()))
+    spec['keycodes'] = dict(sorted(spec.get('keycodes', {}).items()))
 
     # Validate?
     _validate(spec)
@@ -46,12 +75,20 @@ def load_spec(version):
     return spec
 
 
-def list_versions():
+def list_versions(lang=None):
     """Return available versions - sorted newest first
     """
-    ret = []
-    for file in CONSTANTS_PATH.glob('keycodes_[0-9].[0-9].[0-9].hjson'):
-        ret.append(file.stem.split('_')[1])
+    path = _search_path(lang)
+    prefix = _search_prefix(lang)
+
+    return _find_versions(path, prefix)
+
+
+def list_languages():
+    """Return available languages
+    """
+    ret = set()
+    for file in EXTRAS_PATH.glob('keycodes_*_[0-9].[0-9].[0-9].hjson'):
+        ret.add(file.stem.split('_')[1])
 
-    ret.sort(reverse=True)
     return ret
diff --git a/quantum/keymap_extras/keymap_uk.h b/quantum/keymap_extras/keymap_uk.h
index 03fe8149f0..a6c42eafbf 100644
--- a/quantum/keymap_extras/keymap_uk.h
+++ b/quantum/keymap_extras/keymap_uk.h
@@ -1,39 +1,33 @@
-/* Copyright 2015-2016 Jack Humbert
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
+// Copyright 2022 QMK
+// SPDX-License-Identifier: GPL-2.0-or-later
 
-#pragma once
+/*******************************************************************************
+  88888888888 888      d8b                .d888 d8b 888               d8b
+      888     888      Y8P               d88P"  Y8P 888               Y8P
+      888     888                        888        888
+      888     88888b.  888 .d8888b       888888 888 888  .d88b.       888 .d8888b
+      888     888 "88b 888 88K           888    888 888 d8P  Y8b      888 88K
+      888     888  888 888 "Y8888b.      888    888 888 88888888      888 "Y8888b.
+      888     888  888 888      X88      888    888 888 Y8b.          888      X88
+      888     888  888 888  88888P'      888    888 888  "Y8888       888  88888P'
+                                                        888                 888
+                                                        888                 888
+                                                        888                 888
+     .d88b.   .d88b.  88888b.   .d88b.  888d888 8888b.  888888 .d88b.   .d88888
+    d88P"88b d8P  Y8b 888 "88b d8P  Y8b 888P"      "88b 888   d8P  Y8b d88" 888
+    888  888 88888888 888  888 88888888 888    .d888888 888   88888888 888  888
+    Y88b 888 Y8b.     888  888 Y8b.     888    888  888 Y88b. Y8b.     Y88b 888
+     "Y88888  "Y8888  888  888  "Y8888  888    "Y888888  "Y888 "Y8888   "Y88888
+         888
+    Y8b d88P
+     "Y88P"
+*******************************************************************************/
 
+#pragma once
 #include "keymap.h"
-
 // clang-format off
 
-/*
- * ┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───────┐
- * │ ` │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │ 8 │ 9 │ 0 │ - │ = │       │
- * ├───┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─────┤
- * │     │ Q │ W │ E │ R │ T │ Y │ U │ I │ O │ P │ [ │ ] │     │
- * ├─────┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┐    │
- * │      │ A │ S │ D │ F │ G │ H │ J │ K │ L │ ; │ ' │ # │    │
- * ├────┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴───┴────┤
- * │    │ \ │ Z │ X │ C │ V │ B │ N │ M │ , │ . │ / │          │
- * ├────┼───┴┬──┴─┬─┴───┴───┴───┴───┴───┴──┬┴───┼───┴┬────┬────┤
- * │    │    │    │                        │    │    │    │    │
- * └────┴────┴────┴────────────────────────┴────┴────┴────┴────┘
- */
-// Row 1
+// Aliases
 #define UK_GRV  KC_GRV  // `
 #define UK_1    KC_1    // 1
 #define UK_2    KC_2    // 2
@@ -47,7 +41,6 @@
 #define UK_0    KC_0    // 0
 #define UK_MINS KC_MINS // -
 #define UK_EQL  KC_EQL  // =
-// Row 2
 #define UK_Q    KC_Q    // Q
 #define UK_W    KC_W    // W
 #define UK_E    KC_E    // E
@@ -60,7 +53,6 @@
 #define UK_P    KC_P    // P
 #define UK_LBRC KC_LBRC // [
 #define UK_RBRC KC_RBRC // ]
-// Row 3
 #define UK_A    KC_A    // A
 #define UK_S    KC_S    // S
 #define UK_D    KC_D    // D
@@ -73,7 +65,6 @@
 #define UK_SCLN KC_SCLN // ;
 #define UK_QUOT KC_QUOT // '
 #define UK_HASH KC_NUHS // #
-// Row 4
 #define UK_BSLS KC_NUBS // (backslash)
 #define UK_Z    KC_Z    // Z
 #define UK_X    KC_X    // X
@@ -85,21 +76,6 @@
 #define UK_COMM KC_COMM // ,
 #define UK_DOT  KC_DOT  // .
 #define UK_SLSH KC_SLSH // /
-
-/* Shifted symbols
- * ┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───────┐
- * │ ¬ │ ! │ " │ £ │ $ │ % │ ^ │ & │ * │ ( │ ) │ _ │ + │       │
- * ├───┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─────┤
- * │     │   │   │   │   │   │   │   │   │   │   │ { │ } │     │
- * ├─────┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┐    │
- * │      │   │   │   │   │   │   │   │   │   │ : │ @ │ ~ │    │
- * ├────┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴───┴────┤
- * │    │ | │   │   │   │   │   │   │   │ < │ > │ ? │          │
- * ├────┼───┴┬──┴─┬─┴───┴───┴───┴───┴───┴──┬┴───┼───┴┬────┬────┤
- * │    │    │    │                        │    │    │    │    │
- * └────┴────┴────┴────────────────────────┴────┴────┴────┴────┘
- */
-// Row 1
 #define UK_NOT  S(UK_GRV)  // ¬
 #define UK_EXLM S(UK_1)    // !
 #define UK_DQUO S(UK_2)    // "
@@ -113,39 +89,21 @@
 #define UK_RPRN S(UK_0)    // )
 #define UK_UNDS S(UK_MINS) // _
 #define UK_PLUS S(UK_EQL)  // +
-// Row 2
 #define UK_LCBR S(UK_LBRC) // {
 #define UK_RCBR S(UK_RBRC) // }
-// Row 3
 #define UK_COLN S(UK_SCLN) // :
 #define UK_AT   S(UK_QUOT) // @
 #define UK_TILD S(UK_HASH) // ~
-// Row 4
 #define UK_PIPE S(UK_BSLS) // |
 #define UK_LABK S(UK_COMM) // <
 #define UK_RABK S(UK_DOT)  // >
 #define UK_QUES S(UK_SLSH) // ?
-
-/* AltGr symbols
- * ┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───────┐
- * │ ¦ │   │   │   │ € │   │   │   │   │   │   │   │   │       │
- * ├───┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─────┤
- * │     │   │   │ É │   │   │   │ Ú │ Í │ Ó │   │   │   │     │
- * ├─────┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┐    │
- * │      │ Á │   │   │   │   │   │   │   │   │   │   │   │    │
- * ├────┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴───┴────┤
- * │    │   │   │   │   │   │   │   │   │   │   │   │          │
- * ├────┼───┴┬──┴─┬─┴───┴───┴───┴───┴───┴──┬┴───┼───┴┬────┬────┤
- * │    │    │    │                        │    │    │    │    │
- * └────┴────┴────┴────────────────────────┴────┴────┴────┴────┘
- */
-// Row 1
 #define UK_BRKP ALGR(UK_GRV)  // ¦
 #define UK_EURO ALGR(UK_4)    // €
-// Row 2
 #define UK_EACU ALGR(KC_E)    // É
 #define UK_UACU ALGR(KC_U)    // Ú
 #define UK_IACU ALGR(KC_I)    // Í
 #define UK_OACU ALGR(KC_O)    // Ó
-// Row 3
 #define UK_AACU ALGR(KC_A)    // Á
+
+
diff --git a/quantum/keymap_extras/keymap_us.h b/quantum/keymap_extras/keymap_us.h
index b18c701679..c5c5285848 100644
--- a/quantum/keymap_extras/keymap_us.h
+++ b/quantum/keymap_extras/keymap_us.h
@@ -1,52 +1,55 @@
 // Copyright 2022 QMK
 // SPDX-License-Identifier: GPL-2.0-or-later
 
-#pragma once
+/*******************************************************************************
+  88888888888 888      d8b                .d888 d8b 888               d8b
+      888     888      Y8P               d88P"  Y8P 888               Y8P
+      888     888                        888        888
+      888     88888b.  888 .d8888b       888888 888 888  .d88b.       888 .d8888b
+      888     888 "88b 888 88K           888    888 888 d8P  Y8b      888 88K
+      888     888  888 888 "Y8888b.      888    888 888 88888888      888 "Y8888b.
+      888     888  888 888      X88      888    888 888 Y8b.          888      X88
+      888     888  888 888  88888P'      888    888 888  "Y8888       888  88888P'
+                                                        888                 888
+                                                        888                 888
+                                                        888                 888
+     .d88b.   .d88b.  88888b.   .d88b.  888d888 8888b.  888888 .d88b.   .d88888
+    d88P"88b d8P  Y8b 888 "88b d8P  Y8b 888P"      "88b 888   d8P  Y8b d88" 888
+    888  888 88888888 888  888 88888888 888    .d888888 888   88888888 888  888
+    Y88b 888 Y8b.     888  888 Y8b.     888    888  888 Y88b. Y8b.     Y88b 888
+     "Y88888  "Y8888  888  888  "Y8888  888    "Y888888  "Y888 "Y8888   "Y88888
+         888
+    Y8b d88P
+     "Y88P"
+*******************************************************************************/
 
+#pragma once
 #include "keymap.h"
-
 // clang-format off
 
-/* Shifted symbols
- * ┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───────┐
- * │ ~ │ ! │ @ │ # │ $ │ % │ ^ │ & │ * │ ( │ ) │ _ │ + │       │
- * ├───┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─────┤
- * │     │   │   │   │   │   │   │   │   │   │   │ { │ } │  |  │
- * ├─────┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴─────┤
- * │      │   │   │   │   │   │   │   │   │   │ : │ " │        │
- * ├──────┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴────────┤
- * │        │   │   │   │   │   │   │   │ < │ > │ ? │          │
- * ├────┬───┴┬──┴─┬─┴───┴───┴───┴───┴───┴──┬┴───┼───┴┬────┬────┤
- * │    │    │    │                        │    │    │    │    │
- * └────┴────┴────┴────────────────────────┴────┴────┴────┴────┘
- */
-// Row 1
+// Aliases
 #define KC_TILD S(KC_GRAVE) // ~
-#define KC_EXLM S(KC_1)     // !
-#define KC_AT   S(KC_2)     // @
-#define KC_HASH S(KC_3)     // #
-#define KC_DLR  S(KC_4)     // $
-#define KC_PERC S(KC_5)     // %
-#define KC_CIRC S(KC_6)     // ^
-#define KC_AMPR S(KC_7)     // &
-#define KC_ASTR S(KC_8)     // *
-#define KC_LPRN S(KC_9)     // (
-#define KC_RPRN S(KC_0)     // )
+#define KC_EXLM S(KC_1)    // !
+#define KC_AT   S(KC_2)    // @
+#define KC_HASH S(KC_3)    // #
+#define KC_DLR  S(KC_4)    // $
+#define KC_PERC S(KC_5)    // %
+#define KC_CIRC S(KC_6)    // ^
+#define KC_AMPR S(KC_7)    // &
+#define KC_ASTR S(KC_8)    // *
+#define KC_LPRN S(KC_9)    // (
+#define KC_RPRN S(KC_0)    // )
 #define KC_UNDS S(KC_MINUS) // _
 #define KC_PLUS S(KC_EQUAL) // +
-// Row 2
-#define KC_LCBR S(KC_LEFT_BRACKET)  // {
+#define KC_LCBR S(KC_LEFT_BRACKET) // {
 #define KC_RCBR S(KC_RIGHT_BRACKET) // }
-#define KC_PIPE S(KC_BACKSLASH)     // |
-// Row 3
+#define KC_PIPE S(KC_BACKSLASH) // |
 #define KC_COLN S(KC_SEMICOLON) // :
-#define KC_DQUO S(KC_QUOTE)     // "
-// Row 4
+#define KC_DQUO S(KC_QUOTE) // "
 #define KC_LABK S(KC_COMMA) // <
-#define KC_RABK S(KC_DOT)   // >
+#define KC_RABK S(KC_DOT)  // >
 #define KC_QUES S(KC_SLASH) // ?
 
-// alias stuff
 #define KC_TILDE KC_TILD
 #define KC_EXCLAIM KC_EXLM
 #define KC_DOLLAR KC_DLR
@@ -57,16 +60,14 @@
 #define KC_LEFT_PAREN KC_LPRN
 #define KC_RIGHT_PAREN KC_RPRN
 #define KC_UNDERSCORE KC_UNDS
-
 #define KC_LEFT_CURLY_BRACE KC_LCBR
 #define KC_RIGHT_CURLY_BRACE KC_RCBR
-
 #define KC_COLON KC_COLN
 #define KC_DOUBLE_QUOTE KC_DQUO
 #define KC_DQT KC_DQUO
-
 #define KC_LEFT_ANGLE_BRACKET KC_LABK
 #define KC_LT KC_LABK
 #define KC_RIGHT_ANGLE_BRACKET KC_RABK
 #define KC_GT KC_RABK
 #define KC_QUESTION KC_QUES
+