#!/bin/bash # ============================================================================= # machine-setup — system configuration # ============================================================================= # # Definitions only, like the other lib/ files. Locale, and the system-level # settings that follow it. [[ -n "${MACHINE_SETUP_SYSTEM_LOADED:-}" ]] && return 0 MACHINE_SETUP_SYSTEM_LOADED=1 # ----------------------------------------------------------------------------- # Locale # ----------------------------------------------------------------------------- # # Two separate facts, and the original only handled one of them: # # what a new login shell is told to use — LANG in /etc/default/locale # whether that locale actually exists — whether it has been generated # # Setting LANG to a locale that was never generated is the state that produces # "setlocale: LC_ALL: cannot change locale" on every ssh login and every perl # invocation. Both are checked, so the step can say which one is missing. # What a new login shell will be handed, or empty if nothing is configured. locale_current() { if [[ -r /etc/default/locale ]]; then awk -F= '/^LANG=/ { gsub(/"/, "", $2); print $2 }' /etc/default/locale elif [[ -r /etc/locale.conf ]]; then awk -F= '/^LANG=/ { gsub(/"/, "", $2); print $2 }' /etc/locale.conf fi } # Has this locale actually been built? # # `locale -a` prints en_US.utf8 where the configuration spells it en_US.UTF-8, # so both sides are folded to lower case with the dashes removed before # comparing. A literal match here would report a perfectly good locale missing. locale_is_generated() { local want="${1,,}" want="${want//-/}" locale -a 2>/dev/null | tr '[:upper:]' '[:lower:]' | tr -d '-' | grep -qx "$want" } locale_set() { local want="$1" local escaped="${want//./\\.}" case "$PM" in apt) # locale-gen comes from the `locales` package, which minimal images and # most cloud base images do not ship. Without this the step fails with # "locale-gen: command not found" halfway through. if ! pkg_is_installed locales; then info " installing locales, which provides locale-gen" pkg_install_now locales fi # Uncomment it if it is there commented out, add it if it is absent. # Editing the file rather than passing the name to locale-gen is what makes # it survive: a locale generated by argument alone is lost the next time # anything regenerates from /etc/locale.gen. if grep -qE "^#[[:space:]]*${escaped}[[:space:]]" /etc/locale.gen 2>/dev/null; then sed -i "s/^#[[:space:]]*\(${escaped}[[:space:]]\)/\1/" /etc/locale.gen elif ! grep -qE "^${escaped}[[:space:]]" /etc/locale.gen 2>/dev/null; then # The charset is the part after the dot: en_US.UTF-8 -> UTF-8 echo "${want} ${want##*.}" >>/etc/locale.gen fi locale-gen update-locale LANG="$want" ;; pacman) if grep -qE "^#[[:space:]]*${escaped}[[:space:]]" /etc/locale.gen 2>/dev/null; then sed -i "s/^#[[:space:]]*\(${escaped}[[:space:]]\)/\1/" /etc/locale.gen fi locale-gen echo "LANG=${want}" >/etc/locale.conf ;; dnf) # No locale.gen here — the locales come prebuilt in langpack packages. pkg_install_now "glibc-langpack-${want%%_*}" localectl set-locale "LANG=${want}" ;; brew) warn "macOS has no system locale to set — it is per-user, from the terminal's settings" return 1 ;; esac }