Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 71 additions & 0 deletions core/tabs/utils/locale-setup.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
#!/bin/sh -e
. ../common-script.sh

setLocale() {
if command_exists locale-gen; then
iso=$(curl -4fsSL --max-time 5 https://ifconfig.io/country_code 2>/dev/null) || iso="US"
suggested_locales=$(ls /usr/share/i18n/locales/ | grep -i "$iso" || true)

Check warning on line 7 in core/tabs/utils/locale-setup.sh

View workflow job for this annotation

GitHub Actions / Shellcheck

[shellcheck] reported by reviewdog 🐶 Don't use ls | grep. Use a glob or a for loop with a condition to allow non-alphanumeric filenames. Raw Output: ./core/tabs/utils/locale-setup.sh:7:29: warning: Don't use ls | grep. Use a glob or a for loop with a condition to allow non-alphanumeric filenames. (ShellCheck.SC2010)
Comment on lines +6 to +7

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/sh
set -e

printf 'Repository files matching locale-setup.sh:\n'
fd -a 'locale-setup\.sh$' . || true

file="$(fd 'locale-setup\.sh$' . | head -n 1 || true)"
if [ -n "$file" ]; then
  printf '\nFile: %s\n' "$file"
  wc -l "$file"
  cat -n "$file"
fi

printf '\nRelevant grep/iso usages in core/tabs/utils/locale-setup.sh:\n'
if [ -n "$file" ]; then
  rg -n -C 3 'iso=|ifconfig|country_code|suggested_locales|grep|locales/' "$file" || true
fi

printf '\nSample grep behavior with CA on common locale filename set:\n'
python3 - <<'PY'
from pathlib import Path
samples = sorted({
    "ca_ES.utf8",
    "ca_ES@euro",
    "CA",
    "usa",
    "en_US.utf8",
    "de_DE.utf8",
    "us",
    "CA",
})(
    name for name in [
        "ca_ES.utf8", "ca_ES@euro", "CA", "usa", "en_US.utf8", "de_DE.utf8", "us", "CA",
    ]
)
for pattern in ["", "CA", "CA\\b"]:
    print("pattern", repr(pattern), ":")
    for name in samples:
        matched = True
        try:
            import subprocess
            res = subprocess.run(["grep", "-i", pattern, name], input=name+"\n", text=True, capture_output=True)
            matched = res.returncode == 0
        except Exception as e:
            matched = False
        print(name, matched)
PY

Repository: ChrisTitusTech/linutil

Length of output: 5204


🏁 Script executed:

#!/bin/sh
set -e

printf 'Repository files matching locale-setup.sh:\n'
fd 'locale-setup\.sh$' . || true

file="$(fd 'locale-setup\.sh$' . | head -n 1 || true)"
if [ -n "$file" ]; then
  printf '\nFile: %s\n' "$file"
  wc -l "$file"
  cat -n "$file"
fi

printf '\nSample grep behavior with CA on common locale filename set:\n'
python3 - <<'PY'
import subprocess

samples = sorted([
    "ca_ES.utf8",
    "ca_ES@euro",
    "CA",
    "usa",
    "en_US.utf8",
    "de_DE.utf8",
    "us",
    "CA",
])
for pattern in ["", "CA", "CA\\b"]:
    print("pattern", repr(pattern), ":")
    for name in samples:
        result = subprocess.run(["grep", "-i", pattern, name], input=name + "\n", text=True, capture_output=True)
        print(name, result.returncode == 0)
PY

Repository: ChrisTitusTech/linutil

Length of output: 3681


Validate the country code before filtering locales.

iso comes from an HTTP response and is used unanchored in grep. Use ^[A-Za-z]{2}$ and search localeNames for an exact territory match such as _CA, so false positives like ca_* and empty iso values do not enter suggested_locales.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@core/tabs/utils/locale-setup.sh` around lines 6 - 7, Validate iso against the
exact two-letter pattern ^[A-Za-z]{2}$ before filtering, and update the
suggested_locales logic to search localeNames for an exact territory match such
as _CA rather than using an unanchored grep. Ensure invalid or empty responses
produce no suggested locales.


if [ -z "$suggested_locales" ]; then
suggested_locales=$(ls /usr/share/i18n/locales/)
Comment on lines +9 to +10

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Use validated full UTF-8 locale identifiers.

The fallback lists every file in /usr/share/i18n/locales, and the custom branch accepts any regular file below that directory. A path such as ../../../etc/passwd can therefore pass the file check when the target exists, but it is not a locale. The code also rejects standard inputs such as en_GB.UTF-8 and C.UTF-8 unless matching source files exist. Numeric choices produce bare names such as en_GB, which later become LANG=en_GB.

Build choices and custom validation from /usr/share/i18n/SUPPORTED or an equivalent supported-locale list. Special-case C.UTF-8. Keep the source filename separate from the generated locale identifier. Debian documents /usr/share/i18n/SUPPORTED as the supported-locale list and uses full .UTF-8 values for locale configuration. (manpages.debian.org)

Suggested input model
-        suggested_locales=$(ls /usr/share/i18n/locales/ | grep -i "$iso" || true)
+        supported_locales=$(awk '$2 == "UTF-8" { print $1 }' /usr/share/i18n/SUPPORTED)
+        suggested_locales=$(printf '%s\n' "$supported_locales" |
+            grep -iE "(^|_)${iso}([.@]|$)" || true)

         if [ -z "$suggested_locales" ]; then
-            suggested_locales=$(ls /usr/share/i18n/locales/)
+            suggested_locales=$supported_locales
         fi
...
-                if [ -f "/usr/share/i18n/locales/$custom_locale" ]; then
+                if [ "$custom_locale" = "C.UTF-8" ] ||
+                   printf '%s\n' "$supported_locales" |
+                   grep -qxF "$custom_locale"; then

Also applies to: 24-40, 48-52

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@core/tabs/utils/locale-setup.sh` around lines 9 - 10, Update the locale
selection and validation logic around suggested_locales to derive choices from
/usr/share/i18n/SUPPORTED (or an equivalent supported-locale list), accepting
only validated full UTF-8 identifiers and special-casing C.UTF-8. Keep each
source filename separate from its generated locale identifier, reject traversal
or arbitrary files in custom input, and ensure numeric selections and LANG
values retain the .UTF-8 suffix.

fi

printf "%s\n" "Suggested locales based on your location ($iso):"
i=1
for loc in $suggested_locales; do
printf " %d) %s\n" "$i" "$loc"
i=$((i + 1))
done
printf " %s\n" "c) Enter a custom locale"

printf "%s" "Select a locale number (or 'c' for custom): "
read -r choice

if [ "$choice" = "c" ] || [ "$choice" = "C" ]; then
LOCALE=""
while [ -z "$LOCALE" ]; do
printf "%s" "Enter locale (e.g. en_US): "
read -r custom_locale

if [ -z "$custom_locale" ]; then
printf "%s\n" "Locale cannot be empty."
continue
fi

if [ -f "/usr/share/i18n/locales/$custom_locale" ]; then
LOCALE="$custom_locale"
else
printf "%s\n" "'$custom_locale' is not a recognized locale. Please try again."
fi
done
else
case "$choice" in
''|*[!0-9]*)
printf "%s\n" "Invalid selection."
exit 1
;;
esac
LOCALE=$(printf "%s\n" "$suggested_locales" | sed -n "${choice}p")
if [ -z "$LOCALE" ]; then
printf "%s\n" "Invalid selection."
Comment on lines +42 to +50

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/sh
set -eu

echo "== locate file =="
fd -a 'locale-setup.sh' . || true

echo "== relevant file excerpt =="
if [ -f core/tabs/utils/locale-setup.sh ]; then
  nl -ba core/tabs/utils/locale-setup.sh | sed -n '1,90p'
fi

echo "== sed on input 0p =="
printf 'line\n' | sed -n '0p' || true
printf 'line\n' | sed -n '1p' || true

echo "== sed availability =="
sed --version | head -n 1 || true

Repository: ChrisTitusTech/linutil

Length of output: 424


🏁 Script executed:

#!/bin/sh
set -eu

echo "== relevant file excerpt =="
if [ -f core/tabs/utils/locale-setup.sh ]; then
  awk '{printf "%3d\t%s\n", NR, $0}' core/tabs/utils/locale-setup.sh | sed -n '1,120p'
fi

echo "== shell behavior for sed 0p under set -e =="
tmp="$(mktemp)"
trap 'rm -f "$tmp"' EXIT
printf 'line\n' > "$tmp"
(
  set -e
  sed -n '0p' "$tmp"
  status=$?
  printf 'sed status: %s\n' "$status"
)
status=${status:-0}
printf 'outer status: %s\n' "$status"

Repository: ChrisTitusTech/linutil

Length of output: 3027


Reject 0 before the sed lookup.

The menu uses 1-based numbering, but the current validation allows 0. sed -n '0p' fails before reaching the empty-result check, and because this script runs with set -e, the selection cannot print “Invalid selection.” Reject zero as an invalid choice.

Minimal fix for zero
-                ''|*[!0-9]*)
+                ''|0|*[!0-9]*)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
case "$choice" in
''|*[!0-9]*)
printf "%s\n" "Invalid selection."
exit 1
;;
esac
LOCALE=$(printf "%s\n" "$suggested_locales" | sed -n "${choice}p")
if [ -z "$LOCALE" ]; then
printf "%s\n" "Invalid selection."
case "$choice" in
''|0|*[!0-9]*)
printf "%s\n" "Invalid selection."
exit 1
;;
esac
LOCALE=$(printf "%s\n" "$suggested_locales" | sed -n "${choice}p")
if [ -z "$LOCALE" ]; then
printf "%s\n" "Invalid selection."
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@core/tabs/utils/locale-setup.sh` around lines 42 - 50, Update the numeric
validation in the choice-handling case statement to reject zero before the sed
lookup, while continuing to accept positive integer selections. Preserve the
existing “Invalid selection.” response and avoid invoking sed for a zero choice.

exit 1
fi
fi

if ! grep -qxF "${LOCALE} UTF-8" /etc/locale.gen 2>/dev/null; then
printf '%s UTF-8\n' "$LOCALE" | "$ESCALATION_TOOL" tee -a /etc/locale.gen >/dev/null
fi
if grep -q '^LANG=' /etc/locale.conf 2>/dev/null; then
"$ESCALATION_TOOL" sed -i "s/^LANG=.*/LANG=${LOCALE}/" /etc/locale.conf
else
printf 'LANG=%s\n' "$LOCALE" | "$ESCALATION_TOOL" tee -a /etc/locale.conf >/dev/null
fi
"$ESCALATION_TOOL" locale-gen "${LOCALE}"
else
printf "%b\n" "ERROR! locale-gen not found; cannot generate locales on this system."
exit 1
fi
}

checkEnv
Comment thread
technicks89 marked this conversation as resolved.
setLocale
11 changes: 11 additions & 0 deletions core/tabs/utils/tab_data.toml
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,17 @@ name = "Crypto tool"
script = "encrypt_decrypt_tool.sh"
task_list = "I FM"

[[data]]
name = "Locale Setup"
Comment thread
technicks89 marked this conversation as resolved.
description = "This allows the user to set their locale"
script = "locale-setup.sh"
task_list = "FM"

[[data.preconditions]]
matches = true
data = "command_exists"
values = [ "locale-gen" ]

[[data]]
name = "Numlock on Startup"
description = "This utility is designed to enable Num Lock at boot, rather than within desktop environments like KDE or GNOME"
Expand Down
1 change: 1 addition & 0 deletions docs/content/userguide/walkthrough.md
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,7 @@ https://github.com/ChrisTitusTech/dwm-titus

- **Bluetooth Manager**: This utility is designed to manage bluetooth in your system
- **Numlock on Startup**: This utility is designed to enable Num Lock at boot, rather than within desktop environments like KDE or GNOME
- **Locale Setup**: This allows the user to set their locale
- **Ollama**: This utility is designed to manage ollama in your system
- **Ranalama**: This utility is designed to manage ramalama in your system
- **Service Manager**: This utility is designed to manage services in your system
Expand Down
Loading