diff --git a/src/locale.sh b/src/locale.sh new file mode 100644 index 0000000..5da8a18 --- /dev/null +++ b/src/locale.sh @@ -0,0 +1,117 @@ +#!/usr/bin/env bash + +# === Motivation === +# Configure system locale, timezone, and keyboard layout for international users. + +# === Problem Statement === +# A freshly installed system needs localization configuration to support user language and region. + +# === Scope === +# In scope: locale generation, timezone configuration, keyboard layout. +# Out of scope: X11 keyboard configuration, font selection, language packs. + +# === Concepts === +# Locale: Defines language, character encoding, and formatting conventions (LC_*). +# Timezone: Maps local time to UTC with regional rules (DST, etc.). +# Keyboard layout: Console keymap for character input. + +# === Decisions === +# Default locale is en_US.UTF-8 for broadest compatibility. +# Default timezone will be configured based on user prompt (see config.sh). +# Default keyboard layout is 'us' (can be overridden via config). +# Use /etc/default/libc-locales for locale configuration (Void standard). +# Use symlink for timezone (/etc/localtime → /usr/share/zoneinfo/). +# Use /etc/rc.conf for console keyboard layout (KEYMAP variable). + +# === Alternatives Considered === +# systemd-localed rejected (Void uses runit). +# Generating all locales rejected (wastes disk space and time). +# Auto-detection of timezone rejected (unreliable without network/GeoIP). + +# === Constraints === +# Target system must be mounted at $MOUNT_ROOT. +# Locale must be generated before it can be used. +# Timezone must exist in /usr/share/zoneinfo. + +# === Open Questions === +# Should we support multiple locales (e.g., en_US + de_DE)? +# Should we validate timezone path before creating symlink? +# Should we configure X11 keyboard layout as well? + +# === Success Criteria === +# Locale is generated and available in the installed system. +# Timezone is correctly configured and persists after reboot. +# Keyboard layout matches user selection on console login. + +locale_configure() { + : "${MOUNT_ROOT:?Mount root is required}" + : "${LOCALE:?Locale is required}" + : "${TIMEZONE:?Timezone is required}" + : "${KEYBOARD:?Keyboard layout is required}" + + log_info "Locale configuration: setting up locale, timezone, and keyboard" + + # Configure locale in /etc/default/libc-locales + log_info "Configuring locale: $LOCALE" + local locale_file="$MOUNT_ROOT/etc/default/libc-locales" + mkdir -p "$(dirname "$locale_file")" + + # Ensure locale file exists + if [[ ! -f "$locale_file" ]]; then + touch "$locale_file" + fi + + # Uncomment or add the selected locale + if grep -q "^#${LOCALE}" "$locale_file"; then + # Locale exists but is commented - uncomment it + sed -i "s/^#${LOCALE}/${LOCALE}/" "$locale_file" + elif grep -q "^${LOCALE}" "$locale_file"; then + # Locale already enabled + log_info "Locale $LOCALE already enabled" + else + # Add locale to file + echo "$LOCALE UTF-8" >> "$locale_file" + fi + + # Generate locales + log_info "Generating locales (this may take a moment)..." + if ! chroot "$MOUNT_ROOT" xbps-reconfigure -f glibc-locales; then + log_warn "Failed to reconfigure glibc-locales, but continuing" + fi + + # Configure timezone + log_info "Configuring timezone: $TIMEZONE" + local timezone_source="/usr/share/zoneinfo/$TIMEZONE" + local timezone_target="$MOUNT_ROOT/etc/localtime" + + if [[ ! -f "$MOUNT_ROOT$timezone_source" ]]; then + log_warn "Timezone file not found: $timezone_source - using UTC as fallback" + TIMEZONE="UTC" + timezone_source="/usr/share/zoneinfo/UTC" + fi + + # Remove existing symlink or file + rm -f "$timezone_target" + + # Create symlink + ln -sf "$timezone_source" "$timezone_target" + + # Also set timezone in /etc/timezone for compatibility + echo "$TIMEZONE" > "$MOUNT_ROOT/etc/timezone" + + # Configure keyboard layout + log_info "Configuring keyboard layout: $KEYBOARD" + local rc_conf="$MOUNT_ROOT/etc/rc.conf" + + mkdir -p "$(dirname "$rc_conf")" + touch "$rc_conf" + + # Update or add KEYMAP entry in /etc/rc.conf + if grep -q "^KEYMAP=" "$rc_conf"; then + sed -i "s/^KEYMAP=.*/KEYMAP=\"$KEYBOARD\"/" "$rc_conf" + else + echo "KEYMAP=\"$KEYBOARD\"" >> "$rc_conf" + fi + + log_info "Locale configuration complete." +}