#!/usr/bin/env bash # change-system-language-with-zenity.sh # GUI (Zenity) to set system language on Debian (Cinnamon) from a restricted list. # Run from a graphical session with sudo: # sudo -E bash change-system-language-with-zenity.sh set -euo pipefail log() { printf "[*] %s\n" "$*"; } # 0) Must be root if [[ $EUID -ne 0 ]]; then echo "Please run as root (e.g., sudo -E bash $0)." exit 1 fi # 0.1) Require a GUI session if [[ -z "${DISPLAY:-}" ]]; then echo "No DISPLAY detected. Run this from a graphical session." exit 1 fi # 1) Ensure zenity + locales if ! command -v zenity >/dev/null 2>&1; then log "Installing 'zenity'…" apt-get update -y DEBIAN_FRONTEND=noninteractive apt-get install -y zenity fi if ! dpkg -s locales >/dev/null 2>&1; then log "Installing 'locales'…" apt-get update -y DEBIAN_FRONTEND=noninteractive apt-get install -y locales fi SUPPORTED_FILE="/usr/share/i18n/SUPPORTED" if [[ ! -f "$SUPPORTED_FILE" ]]; then zenity --error --title="Locale List Missing" \ --text="Cannot find $SUPPORTED_FILE. Aborting." exit 1 fi # 2) Restrict choices to ONLY these locales # (Adjust here if you want different variants.) REQUESTED_LOCALES=( "en_US.UTF-8" # English (United States) "fa_IR.UTF-8" # Persian (Iran) "ar_SA.UTF-8" # Arabic (Saudi Arabia) "uk_UA.UTF-8" # Ukrainian (Ukraine) "de_DE.UTF-8" # German (Germany) "fr_FR.UTF-8" ) # Keep only those actually listed in SUPPORTED (prevents locale-gen errors) mapfile -t AVAILABLE_LOCALES < <( grep -E '^\S+\s+UTF-8' "$SUPPORTED_FILE" \ | awk '{print $1}' \ | grep -Fx -f <(printf "%s\n" "${REQUESTED_LOCALES[@]}") \ | sort -u ) if (( ${#AVAILABLE_LOCALES[@]} == 0 )); then zenity --error --title="No Locales Available" \ --text="None of the requested locales are available on this system." exit 1 fi # Friendly labels friendly_label() { case "$1" in en_US.UTF-8) echo "English (United States) — en_US.UTF-8";; fr_FR.UTF-8) echo "French (France) - fr_FR.UTF-8";; fa_IR.UTF-8) echo "Persian (Farsi, Iran) — fa_IR.UTF-8";; ar_SA.UTF-8) echo "Arabic (Saudi Arabia) — ar_SA.UTF-8";; uk_UA.UTF-8) echo "Ukrainian (Ukraine) — uk_UA.UTF-8";; de_DE.UTF-8) echo "German (Germany) — de_DE.UTF-8";; *) echo "$1";; esac } # 3) Build Zenity radiolist (default en_US if present else first) ZENITY_ARGS=() DEFAULT="en_US.UTF-8" for loc in "${AVAILABLE_LOCALES[@]}"; do selected="FALSE" [[ "$loc" == "$DEFAULT" ]] && selected="TRUE" ZENITY_ARGS+=("$selected" "$loc" "$(friendly_label "$loc")") done if ! printf '%s\n' "${AVAILABLE_LOCALES[@]}" | grep -q '^en_US\.UTF-8$'; then ZENITY_ARGS[0]="TRUE" fi CHOICE="$(zenity --list \ --radiolist \ --title="Choose System Language" \ --width=700 --height=420 \ --column="Select" --column="Locale" --column="Description" \ "${ZENITY_ARGS[@]}")" || true [[ -z "${CHOICE:-}" ]] && exit 0 # user cancelled TARGET_LOCALE="$CHOICE" TARGET_LANG_LINE="${TARGET_LOCALE} UTF-8" zenity --question \ --title="Confirm Language Change" \ --text="Set the system language to:\n\n${TARGET_LOCALE}\n\nThis updates /etc/locale.gen, runs locale-gen, and sets defaults via update-locale.\nLog out or reboot for Cinnamon to fully apply it." \ --no-wrap \ --ok-label="Apply" --cancel-label="Cancel" || exit 0 # Generate if ! locale-gen 2> >(tee /tmp/locale-gen.err >&2); then zenity --error --title="locale-gen failed" \ --text="locale-gen encountered an error.\n\nSee /tmp/locale-gen.err for details." exit 1 fi # Set system defaults update-locale LANG="${TARGET_LOCALE}" LANGUAGE="${TARGET_LOCALE%%.*}:en" # Mirror LANG in /etc/environment if grep -q '^LANG=' /etc/environment 2>/dev/null; then sed -i "s/^LANG=.*/LANG=${TARGET_LOCALE}/" /etc/environment else echo "LANG=${TARGET_LOCALE}" >> /etc/environment fi zenity --info --title="Language Updated" \ --text="System default language set to:\n\n${TARGET_LOCALE}\n\nLog out and back in (or reboot) for Cinnamon to apply it to your desktop session." \ --no-wrap