Repository: archlinux/archinstall

Issue:
Locale entry in `/etc/locale.gen` is appended rather than uncommented
This deviates from the ArchWiki _Installation guide_ instructions which states to uncomment.

https://wiki.archlinux.org/title/Installation_guide#Localization

https://github.com/archlinux/archinstall/blob/e41900a25cfbf35e550863a8415a0c7a29c9e9b2/archinstall/lib/installer.py#L389-L390
Set `LANG` variable not always consistent with ArchWiki instructions
Following the ArchWiki, the `LANG` variable is set to:

> ... the **first column** of an uncommented entry in `/etc/locale.gen`

https://wiki.archlinux.org/title/Locale#Setting_the_system_locale

Locale entries in `/etc/locale.gen` may or may not include the encoding in the first column. For example, the first column for the locale entry `en_US.UTF-8 UTF-8` contains the encoding while `en_ZM UTF-8` does not. The implementation to set the `LANG` variable will deviate from the ArchWiki instructions when the encoding was not included in the first column of the entry since the encoding is always being included.

https://github.com/archlinux/archinstall/blob/e41900a25cfbf35e550863a8415a0c7a29c9e9b2/archinstall/lib/installer.py#L392


Discussion:

Resolving patch:
diff --git a/archinstall/lib/installer.py b/archinstall/lib/installer.py
--- a/archinstall/lib/installer.py
+++ b/archinstall/lib/installer.py
@@ -366,7 +366,7 @@ def set_hostname(self, hostname: str, *args :str, **kwargs :str) -> None:
 		with open(f'{self.target}/etc/hostname', 'w') as fh:
 			fh.write(hostname + '\n')
 
-	def set_locale(self, locale_config: LocaleConfiguration):
+	def set_locale(self, locale_config: LocaleConfiguration) -> bool:
 		modifier = ''
 		lang = locale_config.sys_lang
 		encoding = locale_config.sys_enc
@@ -386,15 +386,32 @@ def set_locale(self, locale_config: LocaleConfiguration):
 			modifier = f"@{modifier}"
 		# - End patch
 
-		with open(f'{self.target}/etc/locale.gen', 'a') as fh:
-			fh.write(f'{lang}.{encoding}{modifier} {encoding}\n')
+		locale_gen = self.target / 'etc/locale.gen'
+		locale_gen_lines = locale_gen.read_text().splitlines(True)
 
-		(self.target / "etc" / "locale.conf").write_text(f'LANG={lang}.{encoding}{modifier}\n')
+		# A locale entry in /etc/locale.gen may or may not contain the encoding
+		# in the first column of the entry; check for both cases.
+		entry_re = re.compile(rf'#{lang}(\.{encoding})?{modifier} {encoding}')
+
+		for index, line in enumerate(locale_gen_lines):
+			if entry_re.match(line):
+				uncommented_line = line.removeprefix('#')
+				locale_gen_lines[index] = uncommented_line
+				locale_gen.write_text(''.join(locale_gen_lines))
+				lang_value = uncommented_line.split()[0]
+				break
+		else:
+			error(f"Invalid locale: language '{locale_config.sys_lang}', encoding '{locale_config.sys_enc}'")
+			return False
 
 		try:
 			SysCommand(f'/usr/bin/arch-chroot {self.target} locale-gen')
 		except SysCallError as e:
 			error(f'Failed to run locale-gen on target: {e}')
+			return False
+
+		(self.target / 'etc/locale.conf').write_text(f'LANG={lang_value}\n')
+		return True
 
 	def set_timezone(self, zone :str, *args :str, **kwargs :str) -> bool:
 		if not zone:


Test patch: