Issue/Bug description
The password prompt shown by cosmic-greeter (and presumably other text sourced
directly from PAM, e.g. via pam_get_authtok()) is always displayed in English
("Password: "), even when the system locale is correctly set to a non-English
language (in my case Polish, pl_PL.UTF-8).
This is separate from cosmic-greeter's own Fluent-based UI strings (buttons,
tooltips, dialogs, etc. via fl!()), which are correctly localized. Only the
prompt text that comes from PAM itself (via Message::Prompt /
widget::secure_input(prompt.clone(), ...) in src/greeter.rs) stays in
English.
Steps to reproduce
-
Install Pop!_OS / a system with cosmic-greeter, with the system language
set to a non-English locale (tested with Polish, pl_PL.UTF-8).
-
Confirm the locale is correctly generated and set system-wide:
locale -a | grep pl_PL
-> pl_PL.utf8
cat /etc/default/locale
-> LANG=pl_PL.UTF-8
systemctl show-environment | grep LANG
-> LANG=pl_PL.UTF-8
-
Confirm the greetd process (running cosmic-greeter) inherits this LANG:
pid=$(pgrep -f "greetd --config")
cat /proc/$pid/environ | tr '\0' '\n' | grep -i lang
-> LANG=pl_PL.UTF-8
-
Confirm the translation itself exists and works correctly outside the
greeter process:
LANG=pl_PL.utf8 LC_ALL=pl_PL.utf8 gettext -d Linux-PAM "Password: "
-> "Hasło: " (correct)
-
Log out / reboot and look at the cosmic-greeter login screen.
Expected behavior
The password prompt should read "Hasło: " (or whatever the current PAM
translation is for the active locale), matching the rest of the localized UI.
Actual behavior
The prompt is always "Password: " in English, regardless of LANG.
Root cause analysis
libpam's pam_get_authtok() (in linux-pam/libpam/pam_get_authtok.c)
generates its default prompt via classic gettext():
#define PROMPT _("Password: ")
...
retval = pam_prompt (pamh, PAM_PROMPT_ECHO_OFF, &resp[0], "%s", PROMPT);
gettext()/glibc message translation depends on the process having called
setlocale(LC_ALL, "") (or equivalent) at startup -- simply having LANG set
in the environment is not sufficient on its own; the C runtime must
explicitly read it into the active locale.
cosmic-greeter's main() in src/greeter.rs only initializes its own
Fluent-based i18n system:
pub fn main() -> Result<(), Box> {
env_logger::Builder::from_env(...).init();
crate::localize::localize();
...
crate::localize::localize() sets up the Fluent/i18n-embed loader used for
fl!() strings, but (as far as I can tell from the source) never calls libc's
setlocale(). Since pam-client (used to talk to PAM) is a thin FFI wrapper
around libpam and does not call setlocale() either, the process-wide C
locale remains at the default "C" locale for the entire lifetime of
cosmic-greeter -- which means every gettext() call made inside libpam
(including the password prompt) is always rendered in English, independent of
the LANG environment variable.
This was confirmed by testing: gettext -d Linux-PAM "Password: " correctly
returns the Polish translation when run manually (because the gettext CLI
tool calls setlocale() on startup), but the same translation is never
reflected in the actual cosmic-greeter password field.
The pl translation itself is present and correctly installed
(language-pack-pl-base -> /usr/share/locale-langpack/pl/LC_MESSAGES/Linux-PAM.mo),
so this is not a missing-translation issue -- it's a missing setlocale() call.
Suggested fix
Call libc::setlocale(libc::LC_ALL, c"".as_ptr()) (or the equivalent safe
wrapper) early in main(), before any PAM interaction happens, so that
gettext()-based strings coming from libpam respect the system locale the
same way the Fluent-based UI strings already do.
Environment
- Distribution: Pop!_OS 24.04 LTS (COSMIC)
- cosmic-greeter version:
0.1.0~1785340297~24.04~f64e2d8
- Locale tested: pl_PL.UTF-8
Issue/Bug description
The password prompt shown by cosmic-greeter (and presumably other text sourced
directly from PAM, e.g. via
pam_get_authtok()) is always displayed in English("Password: "), even when the system locale is correctly set to a non-English
language (in my case Polish,
pl_PL.UTF-8).This is separate from cosmic-greeter's own Fluent-based UI strings (buttons,
tooltips, dialogs, etc. via
fl!()), which are correctly localized. Only theprompt text that comes from PAM itself (via
Message::Prompt/widget::secure_input(prompt.clone(), ...)insrc/greeter.rs) stays inEnglish.
Steps to reproduce
Install Pop!_OS / a system with cosmic-greeter, with the system language
set to a non-English locale (tested with Polish,
pl_PL.UTF-8).Confirm the locale is correctly generated and set system-wide:
locale -a | grep pl_PL
-> pl_PL.utf8
cat /etc/default/locale
-> LANG=pl_PL.UTF-8
systemctl show-environment | grep LANG
-> LANG=pl_PL.UTF-8
Confirm the greetd process (running cosmic-greeter) inherits this LANG:
pid=$(pgrep -f "greetd --config")
cat /proc/$pid/environ | tr '\0' '\n' | grep -i lang
-> LANG=pl_PL.UTF-8
Confirm the translation itself exists and works correctly outside the
greeter process:
LANG=pl_PL.utf8 LC_ALL=pl_PL.utf8 gettext -d Linux-PAM "Password: "
-> "Hasło: " (correct)
Log out / reboot and look at the cosmic-greeter login screen.
Expected behavior
The password prompt should read "Hasło: " (or whatever the current PAM
translation is for the active locale), matching the rest of the localized UI.
Actual behavior
The prompt is always "Password: " in English, regardless of LANG.
Root cause analysis
libpam's pam_get_authtok() (in linux-pam/libpam/pam_get_authtok.c)
generates its default prompt via classic gettext():
#define PROMPT _("Password: ")
...
retval = pam_prompt (pamh, PAM_PROMPT_ECHO_OFF, &resp[0], "%s", PROMPT);
gettext()/glibc message translation depends on the process having called
setlocale(LC_ALL, "") (or equivalent) at startup -- simply having LANG set
in the environment is not sufficient on its own; the C runtime must
explicitly read it into the active locale.
cosmic-greeter's main() in src/greeter.rs only initializes its own
Fluent-based i18n system:
pub fn main() -> Result<(), Box> {
env_logger::Builder::from_env(...).init();
crate::localize::localize();
...
crate::localize::localize() sets up the Fluent/i18n-embed loader used for
fl!() strings, but (as far as I can tell from the source) never calls libc's
setlocale(). Since pam-client (used to talk to PAM) is a thin FFI wrapper
around libpam and does not call setlocale() either, the process-wide C
locale remains at the default "C" locale for the entire lifetime of
cosmic-greeter -- which means every gettext() call made inside libpam
(including the password prompt) is always rendered in English, independent of
the LANG environment variable.
This was confirmed by testing:
gettext -d Linux-PAM "Password: "correctlyreturns the Polish translation when run manually (because the gettext CLI
tool calls setlocale() on startup), but the same translation is never
reflected in the actual cosmic-greeter password field.
The pl translation itself is present and correctly installed
(language-pack-pl-base -> /usr/share/locale-langpack/pl/LC_MESSAGES/Linux-PAM.mo),
so this is not a missing-translation issue -- it's a missing setlocale() call.
Suggested fix
Call libc::setlocale(libc::LC_ALL, c"".as_ptr()) (or the equivalent safe
wrapper) early in main(), before any PAM interaction happens, so that
gettext()-based strings coming from libpam respect the system locale the
same way the Fluent-based UI strings already do.
Environment
0.1.0~1785340297~24.04~f64e2d8