Skip to content

PAM prompts (e.g. "Password:") are never localized despite correct LANG environment variable #504

Description

@lxsnowy

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

  1. 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).

  2. 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

  3. 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

  4. 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)

  5. 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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions