├── README.md └── 16international /README.md: -------------------------------------------------------------------------------- 1 | # casper Language Autodetection 2 | 3 | ## User story 4 | 5 | As a user of Ubuntu based Live systems, I would like to have the keyboard layout (keyboard language) autodetected. I find it very cumbersome to select the keyboard layout each time I boot a Ubuntu based Live system. 6 | 7 | Ideally, I would also like to get sensible defaults for the locale (application language) and timezone based on that. 8 | 9 | https://www.youtube.com/watch?v=_pWRVR1Knfo around 43:50 shows that the Apple Lisa could set the system language automatically depending on which language keyboard was attaced. In 1983! 10 | 11 | ## Theory of operation 12 | 13 | Ubuntu Live systems are using casper to configure the Live system during the boot process. [casper](https://packages.ubuntu.com/search?keywords=casper&searchon=names) is modular and runs various scripts that become part of the initrd. 14 | 15 | By adding one more script, we can autodetect the keyboard layout (keyboard language) based on the following indicators: 16 | 17 | * [Raspberry Pi Keyboard and Hub](https://www.raspberrypi.com/products/raspberry-pi-keyboard-and-hub/) USB information ([details](https://gist.github.com/probonopd/9646c69f876ff2b4b879aeb1c1cbc532)) 18 | * The EFI variable `prev-lang:kbd` which is usually set on systems running macOS ([details](https://github.com/helloSystem/hello/wiki/EFI-NVRAM)) 19 | 20 | Additional indicators may be added in the future; please open an issue if you have ideas, e.g., 21 | 22 | * USB keyboards should standardize on a way to communicate their keyboard layout (keyboard language) 23 | * The *nix world should standardize on some EFI NVRAM variables for keyboard layout (keyboard language), locale (application language), timezone, etc. 24 | 25 | It is still possible to override the autodetected values by passing kernel arguments as usual (e.g., `console-setup/layoutcode=de locale=de_DE timezone=Europe/Berlin`). 26 | 27 | ## Status 28 | 29 | * Setting the keyboard layout (keyboard language) works 30 | * Setting the locale (application language) works 31 | * Setting the timezone does not seem to work yet - why? 32 | 33 | Please open an issue in this repository if you know the answer to any of those. 34 | 35 | ## Open questions 36 | 37 | * Where is the source code repository for casper? (Hopefully somewhere on GitHub and not hidden away in Launchpad?) 38 | * Who is the maintainer of casper? 39 | * How can we get this merged into casper eventually? 40 | 41 | Please open an issue in this repository if you know the answer to any of those. 42 | -------------------------------------------------------------------------------- /16international: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Be verbose 4 | set -x 5 | 6 | PREREQ="" 7 | DESCRIPTION="Automatically set international settings..." 8 | 9 | prereqs() 10 | { 11 | echo "$PREREQ" 12 | } 13 | 14 | case $1 in 15 | # get pre-requisites 16 | prereqs) 17 | prereqs 18 | exit 0 19 | ;; 20 | esac 21 | 22 | . /scripts/casper-functions 23 | 24 | log_begin_msg "$DESCRIPTION" 25 | 26 | # The order of these is important; must be like the Raspberry Pi Keyboard and Hub numbering 27 | countries="GB GB FR ES US DE IT JP PT NO SE DK RU TR IL" 28 | languages="en en fr es en de it jp pt nn se fi ru tr he" 29 | timezones="Europe/London Europe/London Europe/Paris Europe/Madrid America/New_York Europe/Berlin Europe/Rome Asia/Tokyo Europe/Lisbon Europe/Oslo Europe/Stockholm Europe/Helsinki Europe/Moscow Europe/Istanbul Europe/Jerusalem" 30 | index_en_GB=1 31 | index_fr=2 32 | index_es=3 33 | index_en_US=4 34 | index_de=5 35 | index_it=6 36 | index_pt_PT=7 37 | index_nb=8 38 | index_se=10 39 | index_fi=11 40 | index_ru=12 41 | index_tr=13 42 | index_he=14 43 | 44 | export LD_LIBRARY_PATH=/root/lib/x86_64-linux-gnu:$LD_LIBRARY_PATH # FIXME: Do not hardcode; use find... instead 45 | 46 | RPI_KBD_NUMBER=$(/root/usr/bin/lsusb | grep -o "RPI Wired Keyboard\ [0-9+]" | cut -d " " -f 4) 47 | if [ -n "$RPI_KBD_NUMBER" ]; then 48 | echo "Raspberry Pi Keyboard and Hub detected" 49 | echo "$RPI_KBD_NUMBER" 50 | # 5 = German 51 | 52 | # Get the language and country at the specified index 53 | selected_country=$(echo "$countries" | cut -d " " -f $((RPI_KBD_NUMBER + 1))) 54 | selected_language=$(echo "$languages" | cut -d " " -f $((RPI_KBD_NUMBER + 1))) 55 | selected_timezone=$(echo "$timezones" | cut -d " " -f $((RPI_KBD_NUMBER + 1))) 56 | 57 | # Print the selected country and language 58 | LOCALE_PREFIX="${selected_language}_${selected_country}" 59 | echo "$LOCALE_PREFIX" 60 | KEYBOARD_LAYOUT="$selected_language" 61 | echo "$KEYBOARD_LAYOUT" 62 | echo "$selected_timezone" 63 | fi 64 | 65 | mount -t efivarfs efivarfs /sys/firmware/efi/efivars # NOTE: efivarfs != efivars 66 | EFI_PREV_LANG_KBD=$(cat '/sys/firmware/efi/efivars/prev-lang:kbd-7c436110-ab2a-4bbb-a880-fe41995c9f82') 67 | if [ -n "$EFI_PREV_LANG_KBD" ]; then 68 | echo "prev-lang:kbd EFI variable detected" 69 | echo "${EFI_PREV_LANG_KBD#?}" 70 | # de:3 = German 71 | 72 | search_language=$(echo "${EFI_PREV_LANG_KBD#?}" | cut -d ":" -f 1) 73 | 74 | # Construct the variable name for the search language 75 | search_variable="index_$search_language" 76 | 77 | # Get the index for the search language using eval 78 | eval search_index="\$$search_variable" 79 | 80 | if [ -n "$search_index" ]; then 81 | echo "Language '$search_language' found at index $search_index" 82 | # Get the language and country at the specified index 83 | selected_country=$(echo "$countries" | cut -d " " -f $((search_index + 1))) 84 | selected_language=$(echo "$languages" | cut -d " " -f $((search_index + 1))) 85 | selected_timezone=$(echo "$timezones" | cut -d " " -f $((search_index + 1))) 86 | 87 | # Print the selected country and language 88 | LOCALE_PREFIX="${selected_language}_${selected_country}" 89 | echo "$LOCALE_PREFIX" 90 | KEYBOARD_LAYOUT="$selected_language" 91 | echo "$KEYBOARD_LAYOUT" 92 | echo "$selected_timezone" 93 | else 94 | echo "Language '$search_language' not found" 95 | fi 96 | 97 | fi 98 | 99 | # LOCALE_PREFIX="de_DE" # The desired locale (application language), e.g., "de_DE" 100 | # KEYBOARD_LAYOUT="de" # The desired keyboard layout (keyboard language), e.g., "de" 101 | 102 | # Set locale (application language) if it has not already been set 103 | # This overrides 14locale which ran before 104 | LEN=$(wc -l /root/etc/locale.gen | cut -d " " -f 1) 105 | if [ "$LEN" -gt 1 ]; then 106 | LOCALE_TO_SET="${LOCALE_PREFIX}.UTF-8" 107 | echo "LANG=\"$LOCALE_TO_SET\"" > /root/etc/default/locale 108 | echo "$LOCALE_TO_SET UTF-8" > /root/etc/locale.gen 109 | chroot /root /usr/sbin/locale-gen --keep-existing 110 | fi 111 | 112 | # Set keyboard layout (keyboard language) 113 | # 19keyboard which runs later may override this 114 | # TODO: May also want to customize XKBMODEL, XKBVARIANT, XKBOPTIONS; see: man keyboard(5) 115 | sed -i -e "s|^XKBLAYOUT=.*|XKBLAYOUT=\"$KEYBOARD_LAYOUT\"|g" /root/etc/default/keyboard 116 | 117 | # Set timezone, e.g., "Etc/UTC" or "Europe/Berlin" 118 | if [ -n "$timezone" ]; then 119 | echo "$selected_timezone" > /root/etc/timezone 120 | fi 121 | 122 | # Be verbose 123 | cat /root/etc/default/locale 124 | cat /root/etc/locale.gen 125 | cat /root/etc/default/keyboard 126 | 127 | log_end_msg 128 | --------------------------------------------------------------------------------