From 06e283961dbee6122b9bfe6550b40019da6cac07 Mon Sep 17 00:00:00 2001
From: Moritz Reinel <129004253+moritz-reinel@users.noreply.github.com>
Date: Sat, 12 Oct 2024 21:26:31 +0200
Subject: [PATCH 1/8] add helper script for keeping lang files in sync with
 Lang.zig

---
 res/lang/cat.ini                |  4 ++-
 res/lang/cs.ini                 | 17 ++++++++++
 res/lang/de.ini                 | 17 ++++++++++
 res/lang/en.ini                 |  6 ++--
 res/lang/es.ini                 |  9 ++++++
 res/lang/fix_missing_entries.py | 40 +++++++++++++++++++++++
 res/lang/fix_missing_entries.sh | 56 +++++++++++++++++++++++++++++++++
 res/lang/fr.ini                 |  9 ++++--
 res/lang/it.ini                 | 17 ++++++++++
 res/lang/pl.ini                 | 17 ++++++++++
 res/lang/pt.ini                 | 17 ++++++++++
 res/lang/pt_BR.ini              | 17 ++++++++++
 res/lang/ro.ini                 | 17 ++++++++++
 res/lang/ru.ini                 | 17 ++++++++++
 res/lang/sr.ini                 | 21 +++++++++++--
 res/lang/sv.ini                 | 17 ++++++++++
 res/lang/tr.ini                 | 17 ++++++++++
 res/lang/uk.ini                 | 17 ++++++++++
 src/config/Lang.zig             |  4 +--
 19 files changed, 326 insertions(+), 10 deletions(-)
 create mode 100644 res/lang/fix_missing_entries.py
 create mode 100644 res/lang/fix_missing_entries.sh

diff --git a/res/lang/cat.ini b/res/lang/cat.ini
index 88ca7358..541898b1 100644
--- a/res/lang/cat.ini
+++ b/res/lang/cat.ini
@@ -6,6 +6,7 @@ err_alloc = assignació de memòria fallida
 err_bounds = índex fora de límits
 err_brightness_change = error en canviar la brillantor
 err_chdir = error en obrir la carpeta home
+
 err_console_dev = error en accedir a la consola
 err_dgn_oob = missatge de registre
 err_domain = domini invàlid
@@ -35,6 +36,7 @@ err_perm_dir = error en canviar el directori actual
 err_perm_group = error en degradar els permisos de grup
 err_perm_user = error en degradar els permisos de l'usuari
 err_pwnam = error en obtenir la informació de l'usuari
+
 err_unknown = ha ocorregut un error desconegut
 err_user_gid = error en establir el GID de l'usuari
 err_user_init = error en inicialitzar usuari
@@ -46,10 +48,10 @@ err_xsessions_open = error en obrir la carpeta de sessions
 insert = inserir
 login = iniciar sessió
 logout = sessió tancada
-no_x11_support = x11 support disabled at compile-time
 no_x11_support = el suport per x11 ha estat desactivat en la compilació
 normal = normal
 numlock = Bloq Num
+
 password = Clau
 restart = reiniciar
 shell = shell
diff --git a/res/lang/cs.ini b/res/lang/cs.ini
index b6a217f5..5beac012 100644
--- a/res/lang/cs.ini
+++ b/res/lang/cs.ini
@@ -1,13 +1,20 @@
+
+
+
 capslock = capslock
 err_alloc = alokace paměti selhala
 err_bounds = index je mimo hranice pole
+
 err_chdir = nelze otevřít domovský adresář
+
 err_console_dev = chyba při přístupu do konzole
 err_dgn_oob = zpráva protokolu
 err_domain = neplatná doména
+
 err_hostname = nelze získat název hostitele
 err_mlock = uzamčení paměti hesel selhalo
 err_null = nulový ukazatel
+
 err_pam = pam transakce selhala
 err_pam_abort = pam transakce přerušena
 err_pam_acct_expired = platnost účtu vypršela
@@ -29,17 +36,27 @@ err_perm_dir = nepodařilo se změnit adresář
 err_perm_group = nepodařilo se snížit skupinová oprávnění
 err_perm_user = nepodařilo se snížit uživatelská oprávnění
 err_pwnam = nelze získat informace o uživateli
+
+
 err_user_gid = nastavení GID uživatele selhalo
 err_user_init = inicializace uživatele selhala
 err_user_uid = nastavení UID uživateli selhalo
+
+
 err_xsessions_dir = nepodařilo se najít složku relací
 err_xsessions_open = nepodařilo se otevřít složku relací
+
 login = uživatel
 logout = odhlášen
+
+
 numlock = numlock
+
 password = heslo
 restart = restartovat
 shell = příkazový řádek
 shutdown = vypnout
+
 wayland = wayland
+
 xinitrc = xinitrc
diff --git a/res/lang/de.ini b/res/lang/de.ini
index e18b9ba3..30a8f442 100644
--- a/res/lang/de.ini
+++ b/res/lang/de.ini
@@ -1,13 +1,20 @@
+
+
+
 capslock = Feststelltaste
 err_alloc = Speicherzuweisung fehlgeschlagen
 err_bounds = Listenindex ist außerhalb des Bereichs
+
 err_chdir = Fehler beim oeffnen des home-ordners
+
 err_console_dev = Zugriff auf die Konsole fehlgeschlagen
 err_dgn_oob = Protokoll Nachricht
 err_domain = Unzulaessige domain
+
 err_hostname = Holen des Hostnames fehlgeschlagen
 err_mlock = Abschließen des Passwortspeichers fehlgeschlagen
 err_null = Null Zeiger
+
 err_pam = pam Transaktion fehlgeschlagen
 err_pam_abort = pam Transaktion abgebrochen
 err_pam_acct_expired = Benutzerkonto abgelaufen
@@ -29,17 +36,27 @@ err_perm_dir = Fehler beim wechseln des Ordners
 err_perm_group = Fehler beim heruntersetzen der Gruppen Berechtigungen
 err_perm_user = Fehler beim heruntersetzen der Nutzer Berechtigungen
 err_pwnam = Holen der Benutzerinformationen fehlgeschlagen
+
+
 err_user_gid = Fehler beim setzen der Gruppen Id des Nutzers
 err_user_init = Initialisierung des Nutzers fehlgeschlagen
 err_user_uid = Setzen der Benutzer Id fehlgeschlagen
+
+
 err_xsessions_dir = Fehler beim finden des Sitzungsordners
 err_xsessions_open = Fehler beim öffnen des Sitzungsordners
+
 login = Anmelden
 logout = Abgemeldet
+
+
 numlock = Numtaste
+
 password = Passwort
 restart = Neustarten
 shell = shell
 shutdown = Herunterfahren
+
 wayland = wayland
+
 xinitrc = xinitrc
diff --git a/res/lang/en.ini b/res/lang/en.ini
index d6a42fe6..f08cca19 100644
--- a/res/lang/en.ini
+++ b/res/lang/en.ini
@@ -6,6 +6,7 @@ err_alloc = failed memory allocation
 err_bounds = out-of-bounds index
 err_brightness_change = failed to change brightness
 err_chdir = failed to open home folder
+
 err_console_dev = failed to access console
 err_dgn_oob = log message
 err_domain = invalid domain
@@ -47,14 +48,15 @@ err_xsessions_open = failed to open sessions folder
 insert = insert
 login = login
 logout = logged out
-normal = normal
 no_x11_support = x11 support disabled at compile-time
+normal = normal
 numlock = numlock
+
 password = password
 restart = reboot
 shell = shell
 shutdown = shutdown
 sleep = sleep
 wayland = wayland
-xinitrc = xinitrc
 x11 = x11
+xinitrc = xinitrc
diff --git a/res/lang/es.ini b/res/lang/es.ini
index 73a9acdb..23ec27c6 100644
--- a/res/lang/es.ini
+++ b/res/lang/es.ini
@@ -4,13 +4,17 @@ brightness_up = subir brillo
 capslock = Bloq Mayús
 err_alloc = asignación de memoria fallida
 err_bounds = índice fuera de límites
+
 err_chdir = error al abrir la carpeta home
+
 err_console_dev = error al acceder a la consola
 err_dgn_oob = mensaje de registro
 err_domain = dominio inválido
+
 err_hostname = error al obtener el nombre de host
 err_mlock = error al bloquear la contraseña de memoria
 err_null = puntero nulo
+
 err_pam = error en la transacción pam
 err_pam_abort = transacción pam abortada
 err_pam_acct_expired = cuenta expirada
@@ -32,9 +36,13 @@ err_perm_dir = error al cambiar el directorio actual
 err_perm_group = error al degradar los permisos del grupo
 err_perm_user = error al degradar los permisos del usuario
 err_pwnam = error al obtener la información del usuario
+
+
 err_user_gid = error al establecer el GID del usuario
 err_user_init = error al inicializar usuario
 err_user_uid = error al establecer el UID del usuario
+
+
 err_xsessions_dir = error al buscar la carpeta de sesiones
 err_xsessions_open = error al abrir la carpeta de sesiones
 insert = insertar
@@ -50,4 +58,5 @@ shell = shell
 shutdown = apagar
 sleep = suspender
 wayland = wayland
+
 xinitrc = xinitrc
diff --git a/res/lang/fix_missing_entries.py b/res/lang/fix_missing_entries.py
new file mode 100644
index 00000000..1df81f90
--- /dev/null
+++ b/res/lang/fix_missing_entries.py
@@ -0,0 +1,40 @@
+#!/usr/bin/env python3
+
+from pathlib import Path
+from sys import stderr
+
+
+def process_lang_file(path: str) -> None:
+    values = {}
+    with open(path, "r", encoding="UTF-8") as fh:
+        while line := fh.readline():
+            vals = line.split("=")
+            if len(vals) != 2:
+                continue
+
+            key = vals[0].strip()
+            values[key] = vals[1].strip()
+
+    with open(path, "w", encoding="UTF-8") as fh:
+        for item in lang_strings:
+            v = values.get(item)
+            if v is not None:
+                fh.write(f"{item} = {v}\n")
+            else:
+                fh.write("\n")
+
+
+zig_lang_file = Path(__file__).parent.joinpath("../../src/config/Lang.zig").resolve()
+if not zig_lang_file.exists():
+    print(f"ERROR: File '{zig_lang_file.as_posix()}' does not exist. Exiting.", file=stderr)
+    exit(1)
+
+lang_strings = []
+with open(zig_lang_file, "r", encoding="UTF-8") as fh:
+    while line := fh.readline():
+        lang_strings.append(line.split(":")[0])
+
+lang_files = [f for f in Path.iterdir(Path(__file__).parent) if f.name.endswith(".ini") and f.is_file()]
+
+for file in lang_files:
+    process_lang_file(file.as_posix())
diff --git a/res/lang/fix_missing_entries.sh b/res/lang/fix_missing_entries.sh
new file mode 100644
index 00000000..76c6df35
--- /dev/null
+++ b/res/lang/fix_missing_entries.sh
@@ -0,0 +1,56 @@
+#!/bin/bash
+
+set -eu
+
+function process_lang_file() {
+    local input_file=$1
+    local tmp_file=$(mktemp)
+    local -A lang_strings_in_file
+
+    while read -r line; do
+        if [[ -z "$line" ]]; then
+            :
+        elif [[ "$line" =~ ^([^\ ]*)[\ ]?\=[\ ]?(.*) ]]; then
+            lang_strings_in_file["${BASH_REMATCH[1]}"]="${BASH_REMATCH[2]}"
+        else
+            echo "ERROR: Line '$line' in file '$input_file' does not contain an entry of the pattern '<key> = <value>'. Exiting." >&2
+            exit 1
+        fi
+    done < "$input_file"
+
+    {
+        for s in "${LANG_STRINGS[@]}"; do
+            if [[ -v "lang_strings_in_file[\"$s\"]" ]]; then
+                printf "%s = %s\n" "$s" "${lang_strings_in_file[$s]}"
+            else
+                printf "\n"
+            fi
+        done
+    } > $tmp_file
+
+    mv "$tmp_file" "$input_file"
+}
+
+LANG_DIR=$(dirname "$(realpath $0)")
+
+ZIG_LANG_FILE=$(realpath "$LANG_DIR/../../src/config/Lang.zig")
+
+if [ ! -f "$ZIG_LANG_FILE" ]; then
+    echo "ERROR: File '$ZIG_LANG_FILE' does not exist. Exiting." >&2
+    exit 1
+fi
+
+declare -a LANG_STRINGS
+
+while read -r line; do
+    if [[ "$line" =~ ^([^:]*): ]]; then
+        LANG_STRINGS+=("${BASH_REMATCH[1]}")
+    else
+        echo "ERROR: Line '$line' in file '$ZIG_LANG_FILE' does not contain an entry of the pattern '<lang_item>: ...'." >&2
+        exit 1
+    fi
+done < "$ZIG_LANG_FILE"
+
+for file in $LANG_DIR/*.ini; do
+    process_lang_file "$file"
+done
diff --git a/res/lang/fr.ini b/res/lang/fr.ini
index 5685c95e..a2f45668 100644
--- a/res/lang/fr.ini
+++ b/res/lang/fr.ini
@@ -1,4 +1,4 @@
-authenticating = authentification...
+
 brightness_down = diminuer la luminosité
 brightness_up = augmenter la luminosité
 capslock = verr.maj
@@ -6,6 +6,7 @@ err_alloc = échec d'allocation mémoire
 err_bounds = indice hors-limite
 err_brightness_change = échec du changement de luminosité
 err_chdir = échec de l'ouverture du répertoire home
+
 err_console_dev = échec d'accès à la console
 err_dgn_oob = message
 err_domain = domaine invalide
@@ -35,6 +36,7 @@ err_perm_dir = échec de changement de répertoire
 err_perm_group = échec du déclassement des permissions de groupe
 err_perm_user = échec du déclassement des permissions utilisateur
 err_pwnam = échec de lecture des infos utilisateur
+
 err_unknown = une erreur inconnue est survenue
 err_user_gid = échec de modification du GID
 err_user_init = échec d'initialisation de l'utilisateur
@@ -46,14 +48,15 @@ err_xsessions_open = échec de l'ouverture du dossier de sessions
 insert = insertion
 login = identifiant
 logout = déconnecté
-normal = normal
 no_x11_support = support pour x11 désactivé lors de la compilation
+normal = normal
 numlock = verr.num
+
 password = mot de passe
 restart = redémarrer
 shell = shell
 shutdown = éteindre
 sleep = veille
 wayland = wayland
-xinitrc = xinitrc
 x11 = x11
+xinitrc = xinitrc
diff --git a/res/lang/it.ini b/res/lang/it.ini
index 13eb147b..e9ba7c07 100644
--- a/res/lang/it.ini
+++ b/res/lang/it.ini
@@ -1,13 +1,20 @@
+
+
+
 capslock = capslock
 err_alloc = impossibile allocare memoria
 err_bounds = indice fuori limite
+
 err_chdir = impossibile aprire home directory
+
 err_console_dev = impossibile aprire console
 err_dgn_oob = messaggio log
 err_domain = dominio non valido
+
 err_hostname = impossibile ottenere hostname
 err_mlock = impossibile ottenere lock per la password in memoria
 err_null = puntatore nullo
+
 err_pam = transazione PAM fallita
 err_pam_abort = transazione PAM interrotta
 err_pam_acct_expired = account scaduto
@@ -29,17 +36,27 @@ err_perm_dir = impossibile cambiare directory corrente
 err_perm_group = impossibile ridurre permessi gruppo
 err_perm_user = impossibile ridurre permessi utente
 err_pwnam = impossibile ottenere dati utente
+
+
 err_user_gid = impossibile impostare GID utente
 err_user_init = impossibile inizializzare utente
 err_user_uid = impossible impostare UID utente
+
+
 err_xsessions_dir = impossibile localizzare cartella sessioni
 err_xsessions_open = impossibile aprire cartella sessioni
+
 login = username
 logout = scollegato
+
+
 numlock = numlock
+
 password = password
 restart = riavvio
 shell = shell
 shutdown = arresto
+
 wayland = wayland
+
 xinitrc = xinitrc
diff --git a/res/lang/pl.ini b/res/lang/pl.ini
index f37c4a8d..37d4ff29 100644
--- a/res/lang/pl.ini
+++ b/res/lang/pl.ini
@@ -1,13 +1,20 @@
+
+
+
 capslock = capslock
 err_alloc = nieudana alokacja pamięci
 err_bounds = indeks poza granicami
+
 err_chdir = nie udało się otworzyć folderu domowego
+
 err_console_dev = nie udało się uzyskać dostępu do konsoli
 err_dgn_oob = wiadomość loga
 err_domain = niepoprawna domena
+
 err_hostname = nie udało się uzyskać nazwy hosta
 err_mlock = nie udało się zablokować pamięci haseł
 err_null = wskaźnik zerowy
+
 err_pam = transakcja pam nieudana
 err_pam_abort = transakcja pam przerwana
 err_pam_acct_expired = konto wygasło
@@ -29,17 +36,27 @@ err_perm_dir = nie udało się zmienić obecnego katalogu
 err_perm_group = nie udało się obniżyć uprawnień grupy
 err_perm_user = nie udało się obniżyć uprawnień użytkownika
 err_pwnam = nie udało się uzyskać informacji o użytkowniku
+
+
 err_user_gid = nie udało się ustawić GID użytkownika
 err_user_init = nie udało się zainicjalizować użytkownika
 err_user_uid = nie udało się ustawić UID użytkownika
+
+
 err_xsessions_dir = nie udało się znaleźć folderu sesji
 err_xsessions_open = nie udało się otworzyć folderu sesji
+
 login = login
 logout = wylogowano
+
+
 numlock = numlock
+
 password = hasło
 restart = uruchom ponownie
 shell = powłoka
 shutdown = wyłącz
+
 wayland = wayland
+
 xinitrc = xinitrc
diff --git a/res/lang/pt.ini b/res/lang/pt.ini
index ad2c3976..5d117d78 100644
--- a/res/lang/pt.ini
+++ b/res/lang/pt.ini
@@ -1,13 +1,20 @@
+
+
+
 capslock = capslock
 err_alloc = erro na atribuição de memória
 err_bounds = índice fora de limites
+
 err_chdir = erro ao abrir a pasta home
+
 err_console_dev = erro ao aceder à consola
 err_dgn_oob = mensagem de registo
 err_domain = domínio inválido
+
 err_hostname = erro ao obter o nome do host
 err_mlock = erro de bloqueio de memória
 err_null = ponteiro nulo
+
 err_pam = erro na transação pam
 err_pam_abort = transação pam abortada
 err_pam_acct_expired = conta expirada
@@ -29,17 +36,27 @@ err_perm_dir = erro ao alterar o diretório atual
 err_perm_group = erro ao reduzir as permissões do grupo
 err_perm_user = erro ao reduzir as permissões do utilizador
 err_pwnam = erro ao obter informação do utilizador
+
+
 err_user_gid = erro ao definir o GID do utilizador
 err_user_init = erro ao iniciar o utilizador
 err_user_uid = erro ao definir o UID do utilizador
+
+
 err_xsessions_dir = erro ao localizar a pasta das sessões
 err_xsessions_open = erro ao abrir a pasta das sessões
+
 login = iniciar sessão
 logout = terminar sessão
+
+
 numlock = numlock
+
 password = palavra-passe
 restart = reiniciar
 shell = shell
 shutdown = encerrar
+
 wayland = wayland
+
 xinitrc = xinitrc
diff --git a/res/lang/pt_BR.ini b/res/lang/pt_BR.ini
index 017129a2..f47fc002 100644
--- a/res/lang/pt_BR.ini
+++ b/res/lang/pt_BR.ini
@@ -1,13 +1,20 @@
+
+
+
 capslock = caixa alta
 err_alloc = alocação de memória malsucedida
 err_bounds = índice fora de limites
+
 err_chdir = não foi possível abrir o diretório home
+
 err_console_dev = não foi possível acessar o console
 err_dgn_oob = mensagem de log
 err_domain = domínio inválido
+
 err_hostname = não foi possível obter o nome do host
 err_mlock = bloqueio da memória de senha malsucedido
 err_null = ponteiro nulo
+
 err_pam = transação pam malsucedida
 err_pam_abort = transação pam abortada
 err_pam_acct_expired = conta expirada
@@ -29,17 +36,27 @@ err_perm_dir = não foi possível alterar o diretório atual
 err_perm_group = não foi possível reduzir as permissões de grupo
 err_perm_user = não foi possível reduzir as permissões de usuário
 err_pwnam = não foi possível obter informações do usuário
+
+
 err_user_gid = não foi possível definir o GID do usuário
 err_user_init = não foi possível iniciar o usuário
 err_user_uid = não foi possível definir o UID do usuário
+
+
 err_xsessions_dir = não foi possível encontrar a pasta das sessões
 err_xsessions_open = não foi possível abrir a pasta das sessões
+
 login = conectar
 logout = desconectado
+
+
 numlock = numlock
+
 password = senha
 restart = reiniciar
 shell = shell
 shutdown = desligar
+
 wayland = wayland
+
 xinitrc = xinitrc
diff --git a/res/lang/ro.ini b/res/lang/ro.ini
index 884e9da4..89e92be6 100644
--- a/res/lang/ro.ini
+++ b/res/lang/ro.ini
@@ -1,7 +1,12 @@
+
+
+
 capslock = capslock
 
 
 
+
+
 err_console_dev = nu s-a putut accesa consola
 
 
@@ -9,6 +14,8 @@ err_console_dev = nu s-a putut accesa consola
 
 
 
+
+
 err_pam_abort = tranzacţie pam anulată
 err_pam_acct_expired = cont expirat
 err_pam_auth = eroare de autentificare
@@ -34,12 +41,22 @@ err_perm_user = nu s-a putut face downgrade permisiunilor de utilizator
 
 
 
+
+
+
+
+
 login = utilizator
 logout = opreşte sesiunea
+
+
 numlock = numlock
+
 password = parolă
 restart = resetează
 shell = shell
 shutdown = opreşte sistemul
+
 wayland = wayland
+
 xinitrc = xinitrc
diff --git a/res/lang/ru.ini b/res/lang/ru.ini
index 356ce5fd..a67568a8 100644
--- a/res/lang/ru.ini
+++ b/res/lang/ru.ini
@@ -1,13 +1,20 @@
+
+
+
 capslock = capslock
 err_alloc = не удалось выделить память
 err_bounds = за пределами индекса
+
 err_chdir = не удалось открыть домашнюю папку
+
 err_console_dev = не удалось получить доступ к консоли
 err_dgn_oob = отладочное сообщение (log)
 err_domain = неверный домен
+
 err_hostname = не удалось получить имя хоста
 err_mlock = сбой блокировки памяти
 err_null = нулевой указатель
+
 err_pam = pam транзакция не удалась
 err_pam_abort = pam транзакция прервана
 err_pam_acct_expired = срок действия аккаунта истёк
@@ -29,17 +36,27 @@ err_perm_dir = не удалось изменить текущий катало
 err_perm_group = не удалось понизить права доступа группы
 err_perm_user = не удалось понизить права доступа пользователя
 err_pwnam = не удалось получить информацию о пользователе
+
+
 err_user_gid = не удалось установить GID пользователя
 err_user_init = не удалось инициализировать пользователя
 err_user_uid = не удалось установить UID пользователя
+
+
 err_xsessions_dir = не удалось найти сессионную папку
 err_xsessions_open = не удалось открыть сессионную папку
+
 login = логин
 logout = logged out
+
+
 numlock = numlock
+
 password = пароль
 restart = перезагрузить
 shell = shell
 shutdown = выключить
+
 wayland = wayland
+
 xinitrc = xinitrc
diff --git a/res/lang/sr.ini b/res/lang/sr.ini
index 2f685e39..96b73d8f 100644
--- a/res/lang/sr.ini
+++ b/res/lang/sr.ini
@@ -1,13 +1,20 @@
+
+
+
 capslock = capslock
 err_alloc = neuspijesna alokacija memorije
 err_bounds = izvan granica indeksa
+
 err_chdir = neuspijesno otvaranje home foldera
+
 err_console_dev = neuspijesno pristupanje konzoli
 err_dgn_oob = log poruka
 err_domain = nevazeci domen
+
 err_hostname = neuspijesno trazenje hostname-a
 err_mlock = neuspijesno zakljucavanje memorije lozinke
 err_null = null pokazivac
+
 err_pam = pam transakcija neuspijesna
 err_pam_abort = pam transakcija prekinuta
 err_pam_acct_expired = nalog istekao
@@ -25,21 +32,31 @@ err_pam_session = greska sesije
 err_pam_sys = greska sistema
 err_pam_user_unknown = nepoznat korisnik
 err_path = neuspjelo postavljanje path-a
-err_perm_dir = neuspjelo mijenjanje foldera 
+err_perm_dir = neuspjelo mijenjanje foldera
 err_perm_group = neuspjesno snizavanje dozvola grupe
 err_perm_user = neuspijesno snizavanje dozvola korisnika
 err_pwnam = neuspijesno skupljanje informacija o korisniku
+
+
 err_user_gid = neuspijesno postavljanje korisničkog GID-a
 err_user_init = neuspijensa inicijalizacija korisnika
 err_user_uid = neuspijesno postavljanje UID-a korisnika
+
+
 err_xsessions_dir = neuspijesno pronalazenje foldera sesija
-err_xsessions_open = neuspijesno otvaranje foldera sesija 
+err_xsessions_open = neuspijesno otvaranje foldera sesija
+
 login = korisnik
 logout = izlogovan
+
+
 numlock = numlock
+
 password = lozinka
 restart = ponovo pokreni
 shell = shell
 shutdown = ugasi
+
 wayland = wayland
+
 xinitrc = xinitrc
diff --git a/res/lang/sv.ini b/res/lang/sv.ini
index 46af681c..7ace439b 100644
--- a/res/lang/sv.ini
+++ b/res/lang/sv.ini
@@ -1,13 +1,20 @@
+
+
+
 capslock = capslock
 err_alloc = misslyckad minnesallokering
 err_bounds = utanför banan index
+
 err_chdir = misslyckades att öppna hemkatalog
+
 err_console_dev = misslyckades att komma åt konsol
 err_dgn_oob = loggmeddelande
 err_domain = okänd domän
+
 err_hostname = misslyckades att hämta värdnamn
 err_mlock = misslyckades att låsa lösenordsminne
 err_null = nullpekare
+
 err_pam = pam-transaktion misslyckades
 err_pam_abort = pam-transaktion avbröts
 err_pam_acct_expired = konto upphört
@@ -29,17 +36,27 @@ err_perm_dir = misslyckades att ändra aktuell katalog
 err_perm_group = misslyckades att nergradera gruppbehörigheter
 err_perm_user = misslyckades att nergradera användarbehörigheter
 err_pwnam = misslyckades att hämta användarinfo
+
+
 err_user_gid = misslyckades att ställa in användar-GID
 err_user_init = misslyckades att initialisera användaren
 err_user_uid = misslyckades att ställa in användar-UID
+
+
 err_xsessions_dir = misslyckades att hitta sessionskatalog
 err_xsessions_open = misslyckades att öppna sessionskatalog
+
 login = inloggning
 logout = utloggad
+
+
 numlock = numlock
+
 password = lösenord
 restart = starta om
 shell = skal
 shutdown = stäng av
+
 wayland = wayland
+
 xinitrc = xinitrc
diff --git a/res/lang/tr.ini b/res/lang/tr.ini
index 9bef6171..32dae6e8 100644
--- a/res/lang/tr.ini
+++ b/res/lang/tr.ini
@@ -1,13 +1,20 @@
+
+
+
 capslock = capslock
 err_alloc = basarisiz bellek ayirma
 err_bounds = sinirlarin disinda dizin
+
 err_chdir = ev klasoru acilamadi
+
 err_console_dev = konsola erisilemedi
 err_dgn_oob = log mesaji
 err_domain = gecersiz etki alani
+
 err_hostname = ana bilgisayar adi alinamadi
 err_mlock = parola bellegi kilitlenemedi
 err_null = bos isaretci hatasi
+
 err_pam = pam islemi basarisiz oldu
 err_pam_abort = pam islemi durduruldu
 err_pam_acct_expired = hesabin suresi dolmus
@@ -29,17 +36,27 @@ err_perm_dir = gecerli dizin degistirilemedi
 err_perm_group = grup izinleri dusurulemedi
 err_perm_user = kullanici izinleri dusurulemedi
 err_pwnam = kullanici bilgileri alinamadi
+
+
 err_user_gid = kullanici icin GID ayarlanamadi
 err_user_init = kullanici oturumu baslatilamadi
 err_user_uid = kullanici icin UID ayarlanamadi
+
+
 err_xsessions_dir = oturumlar klasoru bulunamadi
 err_xsessions_open = oturumlar klasoru acilamadi
+
 login = kullanici
 logout = oturumdan cikis yapildi
+
+
 numlock = numlock
+
 password = sifre
 restart = yeniden baslat
 shell = shell
 shutdown = makineyi kapat
+
 wayland = wayland
+
 xinitrc = xinitrc
diff --git a/res/lang/uk.ini b/res/lang/uk.ini
index 5f5b1132..76d48b59 100644
--- a/res/lang/uk.ini
+++ b/res/lang/uk.ini
@@ -1,13 +1,20 @@
+
+
+
 capslock = capslock
 err_alloc = невдале виділення пам'яті
 err_bounds = поза межами індексу
+
 err_chdir = не вдалося відкрити домашній каталог
+
 err_console_dev = невдалий доступ до консолі
 err_dgn_oob = повідомлення журналу (log)
 err_domain = недійсний домен
+
 err_hostname = не вдалося отримати ім'я хосту
 err_mlock = збій блокування пам'яті
 err_null = нульовий вказівник
+
 err_pam = невдала pam транзакція
 err_pam_abort = pam транзакція перервана
 err_pam_acct_expired = термін дії акаунту вичерпано
@@ -29,17 +36,27 @@ err_perm_dir = не вдалося змінити поточний катало
 err_perm_group = не вдалося понизити права доступу групи
 err_perm_user = не вдалося понизити права доступу користувача
 err_pwnam = не вдалося отримати дані користувача
+
+
 err_user_gid = не вдалося змінити GID користувача
 err_user_init = не вдалося ініціалізувати користувача
 err_user_uid = не вдалося змінити UID користувача
+
+
 err_xsessions_dir = не вдалося знайти каталог сесій
 err_xsessions_open = не вдалося відкрити каталог сесій
+
 login = логін
 logout = вийти
+
+
 numlock = numlock
+
 password = пароль
 restart = перезавантажити
 shell = оболонка
 shutdown = вимкнути
+
 wayland = wayland
+
 xinitrc = xinitrc
diff --git a/src/config/Lang.zig b/src/config/Lang.zig
index abe3ed0e..cd5f6893 100644
--- a/src/config/Lang.zig
+++ b/src/config/Lang.zig
@@ -48,8 +48,8 @@ err_xsessions_open: []const u8 = "failed to open sessions folder",
 insert: []const u8 = "insert",
 login: []const u8 = "login:",
 logout: []const u8 = "logged out",
-normal: []const u8 = "normal",
 no_x11_support: []const u8 = "x11 support disabled at compile-time",
+normal: []const u8 = "normal",
 numlock: []const u8 = "numlock",
 other: []const u8 = "other",
 password: []const u8 = "password:",
@@ -58,5 +58,5 @@ shell: [:0]const u8 = "shell",
 shutdown: []const u8 = "shutdown",
 sleep: []const u8 = "sleep",
 wayland: []const u8 = "wayland",
-xinitrc: [:0]const u8 = "xinitrc",
 x11: []const u8 = "x11",
+xinitrc: [:0]const u8 = "xinitrc",

From 7a1fce660cf9e45b2b0ebfb90dffe3d307486776 Mon Sep 17 00:00:00 2001
From: Moritz Reinel <129004253+moritz-reinel@users.noreply.github.com>
Date: Sat, 12 Oct 2024 21:27:19 +0200
Subject: [PATCH 2/8] remove python version of lang script

---
 res/lang/fix_missing_entries.py | 40 ---------------------------------
 1 file changed, 40 deletions(-)
 delete mode 100644 res/lang/fix_missing_entries.py

diff --git a/res/lang/fix_missing_entries.py b/res/lang/fix_missing_entries.py
deleted file mode 100644
index 1df81f90..00000000
--- a/res/lang/fix_missing_entries.py
+++ /dev/null
@@ -1,40 +0,0 @@
-#!/usr/bin/env python3
-
-from pathlib import Path
-from sys import stderr
-
-
-def process_lang_file(path: str) -> None:
-    values = {}
-    with open(path, "r", encoding="UTF-8") as fh:
-        while line := fh.readline():
-            vals = line.split("=")
-            if len(vals) != 2:
-                continue
-
-            key = vals[0].strip()
-            values[key] = vals[1].strip()
-
-    with open(path, "w", encoding="UTF-8") as fh:
-        for item in lang_strings:
-            v = values.get(item)
-            if v is not None:
-                fh.write(f"{item} = {v}\n")
-            else:
-                fh.write("\n")
-
-
-zig_lang_file = Path(__file__).parent.joinpath("../../src/config/Lang.zig").resolve()
-if not zig_lang_file.exists():
-    print(f"ERROR: File '{zig_lang_file.as_posix()}' does not exist. Exiting.", file=stderr)
-    exit(1)
-
-lang_strings = []
-with open(zig_lang_file, "r", encoding="UTF-8") as fh:
-    while line := fh.readline():
-        lang_strings.append(line.split(":")[0])
-
-lang_files = [f for f in Path.iterdir(Path(__file__).parent) if f.name.endswith(".ini") and f.is_file()]
-
-for file in lang_files:
-    process_lang_file(file.as_posix())

From 47ebe641d9200850b4f528146c0d4ee9f7fe54f9 Mon Sep 17 00:00:00 2001
From: Moritz Reinel <129004253+moritz-reinel@users.noreply.github.com>
Date: Sat, 12 Oct 2024 21:51:50 +0200
Subject: [PATCH 3/8] remove necessity for temp file

---
 res/lang/fix_missing_entries.sh | 5 +----
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/res/lang/fix_missing_entries.sh b/res/lang/fix_missing_entries.sh
index 76c6df35..ab63965f 100644
--- a/res/lang/fix_missing_entries.sh
+++ b/res/lang/fix_missing_entries.sh
@@ -4,7 +4,6 @@ set -eu
 
 function process_lang_file() {
     local input_file=$1
-    local tmp_file=$(mktemp)
     local -A lang_strings_in_file
 
     while read -r line; do
@@ -26,9 +25,7 @@ function process_lang_file() {
                 printf "\n"
             fi
         done
-    } > $tmp_file
-
-    mv "$tmp_file" "$input_file"
+    } > "$input_file"
 }
 
 LANG_DIR=$(dirname "$(realpath $0)")

From fe36879dfb5f384e0414f24cd8eb62c4a121112c Mon Sep 17 00:00:00 2001
From: Moritz Reinel <129004253+moritz-reinel@users.noreply.github.com>
Date: Sat, 12 Oct 2024 22:07:29 +0200
Subject: [PATCH 4/8] added note to Lang.zig and updated lang script to not
 process the comment

---
 res/lang/fix_missing_entries.sh | 4 +++-
 src/config/Lang.zig             | 5 +++++
 2 files changed, 8 insertions(+), 1 deletion(-)

diff --git a/res/lang/fix_missing_entries.sh b/res/lang/fix_missing_entries.sh
index ab63965f..8cdaae2b 100644
--- a/res/lang/fix_missing_entries.sh
+++ b/res/lang/fix_missing_entries.sh
@@ -40,7 +40,9 @@ fi
 declare -a LANG_STRINGS
 
 while read -r line; do
-    if [[ "$line" =~ ^([^:]*): ]]; then
+    if [[ -z "$line" || "$line" =~ ^\/\/ ]]; then
+        :
+    elif [[ "$line" =~ ^([^:]*): ]]; then
         LANG_STRINGS+=("${BASH_REMATCH[1]}")
     else
         echo "ERROR: Line '$line' in file '$ZIG_LANG_FILE' does not contain an entry of the pattern '<lang_item>: ...'." >&2
diff --git a/src/config/Lang.zig b/src/config/Lang.zig
index cd5f6893..0e8d6c39 100644
--- a/src/config/Lang.zig
+++ b/src/config/Lang.zig
@@ -1,3 +1,8 @@
+//
+// NOTE: After editing this file, please run `/res/lang/fix_missing_entries.sh`
+//       to update all the language files accordingly.
+//
+
 authenticating: []const u8 = "authenticating...",
 brightness_down: []const u8 = "decrease brightness",
 brightness_up: []const u8 = "increase brightness",

From 7a82b51ac558eb22ec16f6db23baf46201ec04e5 Mon Sep 17 00:00:00 2001
From: Moritz Reinel <129004253+moritz-reinel@users.noreply.github.com>
Date: Mon, 21 Oct 2024 19:42:57 +0200
Subject: [PATCH 5/8] Revert "remove python version of lang script"

This reverts commit 7a1fce660cf9e45b2b0ebfb90dffe3d307486776.
---
 res/lang/fix_missing_entries.py | 40 +++++++++++++++++++++++++++++++++
 1 file changed, 40 insertions(+)
 create mode 100644 res/lang/fix_missing_entries.py

diff --git a/res/lang/fix_missing_entries.py b/res/lang/fix_missing_entries.py
new file mode 100644
index 00000000..1df81f90
--- /dev/null
+++ b/res/lang/fix_missing_entries.py
@@ -0,0 +1,40 @@
+#!/usr/bin/env python3
+
+from pathlib import Path
+from sys import stderr
+
+
+def process_lang_file(path: str) -> None:
+    values = {}
+    with open(path, "r", encoding="UTF-8") as fh:
+        while line := fh.readline():
+            vals = line.split("=")
+            if len(vals) != 2:
+                continue
+
+            key = vals[0].strip()
+            values[key] = vals[1].strip()
+
+    with open(path, "w", encoding="UTF-8") as fh:
+        for item in lang_strings:
+            v = values.get(item)
+            if v is not None:
+                fh.write(f"{item} = {v}\n")
+            else:
+                fh.write("\n")
+
+
+zig_lang_file = Path(__file__).parent.joinpath("../../src/config/Lang.zig").resolve()
+if not zig_lang_file.exists():
+    print(f"ERROR: File '{zig_lang_file.as_posix()}' does not exist. Exiting.", file=stderr)
+    exit(1)
+
+lang_strings = []
+with open(zig_lang_file, "r", encoding="UTF-8") as fh:
+    while line := fh.readline():
+        lang_strings.append(line.split(":")[0])
+
+lang_files = [f for f in Path.iterdir(Path(__file__).parent) if f.name.endswith(".ini") and f.is_file()]
+
+for file in lang_files:
+    process_lang_file(file.as_posix())

From 0dea19c8db7ee14e0a9ccf3abf7e8194e2db672b Mon Sep 17 00:00:00 2001
From: Moritz Reinel <129004253+moritz-reinel@users.noreply.github.com>
Date: Mon, 21 Oct 2024 19:43:33 +0200
Subject: [PATCH 6/8] remove bash version of script

---
 res/lang/fix_missing_entries.sh | 55 ---------------------------------
 1 file changed, 55 deletions(-)
 delete mode 100644 res/lang/fix_missing_entries.sh

diff --git a/res/lang/fix_missing_entries.sh b/res/lang/fix_missing_entries.sh
deleted file mode 100644
index 8cdaae2b..00000000
--- a/res/lang/fix_missing_entries.sh
+++ /dev/null
@@ -1,55 +0,0 @@
-#!/bin/bash
-
-set -eu
-
-function process_lang_file() {
-    local input_file=$1
-    local -A lang_strings_in_file
-
-    while read -r line; do
-        if [[ -z "$line" ]]; then
-            :
-        elif [[ "$line" =~ ^([^\ ]*)[\ ]?\=[\ ]?(.*) ]]; then
-            lang_strings_in_file["${BASH_REMATCH[1]}"]="${BASH_REMATCH[2]}"
-        else
-            echo "ERROR: Line '$line' in file '$input_file' does not contain an entry of the pattern '<key> = <value>'. Exiting." >&2
-            exit 1
-        fi
-    done < "$input_file"
-
-    {
-        for s in "${LANG_STRINGS[@]}"; do
-            if [[ -v "lang_strings_in_file[\"$s\"]" ]]; then
-                printf "%s = %s\n" "$s" "${lang_strings_in_file[$s]}"
-            else
-                printf "\n"
-            fi
-        done
-    } > "$input_file"
-}
-
-LANG_DIR=$(dirname "$(realpath $0)")
-
-ZIG_LANG_FILE=$(realpath "$LANG_DIR/../../src/config/Lang.zig")
-
-if [ ! -f "$ZIG_LANG_FILE" ]; then
-    echo "ERROR: File '$ZIG_LANG_FILE' does not exist. Exiting." >&2
-    exit 1
-fi
-
-declare -a LANG_STRINGS
-
-while read -r line; do
-    if [[ -z "$line" || "$line" =~ ^\/\/ ]]; then
-        :
-    elif [[ "$line" =~ ^([^:]*): ]]; then
-        LANG_STRINGS+=("${BASH_REMATCH[1]}")
-    else
-        echo "ERROR: Line '$line' in file '$ZIG_LANG_FILE' does not contain an entry of the pattern '<lang_item>: ...'." >&2
-        exit 1
-    fi
-done < "$ZIG_LANG_FILE"
-
-for file in $LANG_DIR/*.ini; do
-    process_lang_file "$file"
-done

From b6726a76c6114d747e5f84adb6e23def79d54915 Mon Sep 17 00:00:00 2001
From: Moritz Reinel <129004253+moritz-reinel@users.noreply.github.com>
Date: Sat, 26 Oct 2024 13:09:30 +0200
Subject: [PATCH 7/8] refactored some variables + added comments

---
 res/lang/fix_missing_entries.py | 55 +++++++++++++++++++--------------
 1 file changed, 32 insertions(+), 23 deletions(-)

diff --git a/res/lang/fix_missing_entries.py b/res/lang/fix_missing_entries.py
index 1df81f90..39047379 100644
--- a/res/lang/fix_missing_entries.py
+++ b/res/lang/fix_missing_entries.py
@@ -4,37 +4,46 @@
 from sys import stderr
 
 
-def process_lang_file(path: str) -> None:
-    values = {}
+def process_lang_file(path: Path, lang_keys: list[str]) -> None:
+    # read key-value-pairs from lang file into dict
+    existing_entries = {}
     with open(path, "r", encoding="UTF-8") as fh:
         while line := fh.readline():
-            vals = line.split("=")
-            if len(vals) != 2:
+            try:
+                key, value = line.split("=", 1)
+                existing_entries[key.strip()] = value.strip()
+            except ValueError:  # line does not contain '='
                 continue
 
-            key = vals[0].strip()
-            values[key] = vals[1].strip()
-
+    # re-write current lang file with entries in order of occurence in `lang_keys`
+    # and with empty lines for missing translations
     with open(path, "w", encoding="UTF-8") as fh:
-        for item in lang_strings:
-            v = values.get(item)
-            if v is not None:
-                fh.write(f"{item} = {v}\n")
-            else:
+        for item in lang_keys:
+            try:
+                fh.write(f"{item} = {existing_entries[item]}\n")
+            except KeyError:  # no translation for `item` yet
                 fh.write("\n")
 
 
-zig_lang_file = Path(__file__).parent.joinpath("../../src/config/Lang.zig").resolve()
-if not zig_lang_file.exists():
-    print(f"ERROR: File '{zig_lang_file.as_posix()}' does not exist. Exiting.", file=stderr)
-    exit(1)
+def main() -> None:
+    zig_lang_file = Path(__file__).parent.joinpath("../../src/config/Lang.zig").resolve()
+    if not zig_lang_file.exists():
+        print(f"ERROR: File '{zig_lang_file.as_posix()}' does not exist. Exiting.", file=stderr)
+        exit(1)
+
+    # read "language keys" from `zig_lang_file` into list
+    lang_keys = []
+    with open(zig_lang_file, "r", encoding="UTF-8") as fh:
+        while line := fh.readline():
+            # only process lines that are not empty or no comments
+            if not (line.strip() == "" or line.startswith("//")):
+                lang_keys.append(line.split(":")[0].strip())
+
+    lang_files = [f for f in Path.iterdir(Path(__file__).parent) if f.name.endswith(".ini") and f.is_file()]
 
-lang_strings = []
-with open(zig_lang_file, "r", encoding="UTF-8") as fh:
-    while line := fh.readline():
-        lang_strings.append(line.split(":")[0])
+    for file in lang_files:
+        process_lang_file(file, lang_keys)
 
-lang_files = [f for f in Path.iterdir(Path(__file__).parent) if f.name.endswith(".ini") and f.is_file()]
 
-for file in lang_files:
-    process_lang_file(file.as_posix())
+if __name__ == "__main__":
+    main()

From 117eccd65a44f67a61a328d559f2c4458d94dc20 Mon Sep 17 00:00:00 2001
From: Moritz Reinel <129004253+moritz-reinel@users.noreply.github.com>
Date: Sat, 26 Oct 2024 13:19:33 +0200
Subject: [PATCH 8/8] rename language normalizer script

---
 res/lang/{fix_missing_entries.py => normalize_lang_files.py} | 0
 src/config/Lang.zig                                          | 2 +-
 2 files changed, 1 insertion(+), 1 deletion(-)
 rename res/lang/{fix_missing_entries.py => normalize_lang_files.py} (100%)

diff --git a/res/lang/fix_missing_entries.py b/res/lang/normalize_lang_files.py
similarity index 100%
rename from res/lang/fix_missing_entries.py
rename to res/lang/normalize_lang_files.py
diff --git a/src/config/Lang.zig b/src/config/Lang.zig
index 0e8d6c39..a8ff9fce 100644
--- a/src/config/Lang.zig
+++ b/src/config/Lang.zig
@@ -1,5 +1,5 @@
 //
-// NOTE: After editing this file, please run `/res/lang/fix_missing_entries.sh`
+// NOTE: After editing this file, please run `/res/lang/normalize_lang_files.py`
 //       to update all the language files accordingly.
 //