Thread

  1. Re: PRI?64 vs Visual Studio (2022)

    Bryan Green <dbryan.green@gmail.com> — 2025-12-15T23:10:36Z

    On 12/15/2025 2:39 PM, Tom Lane wrote:
    > I wrote:
    >> Experimenting here, it looks like 'C.UTF-8' might be accepted
    >> everywhere.  I even got it to pass on Solaris's not-GNU gettext,
    >> which I thought for sure would be the weak spot in the idea.
    >> I'll press forward with that.
    > 
    > Hmmm ... the first batch of BF reports show that on some Linux
    > machines, it works to set lc_messages to 'C.UTF-8', but nonetheless
    > no translation happens.  Did you notice any other gating factors?
    > 
    > 			regards, tom lane
    Yes - the LANGUAGE environment variable.
    
    gettext has a priority order for locale selection that's different from
    what most people expect. Here's what guess_category_value() does:
    Environment Variable Priority (from dcigettext.c):
    
    1. LANGUAGE - GNU extension, colon-separated list (e.g., "en_US:en:C")
    2. setlocale(category, NULL) result - the actual locale set
    3. LC_ALL - POSIX override for all categories
    4. LC_MESSAGES (or other LC_* for that category)
    5. LANG - fallback default
    
    LANGUAGE has the highest priority and will override LC_MESSAGES completely.
    
    I am not sure this is the problem, but you probably should unset
    LANGUAGE before doing almost anything else in the test script.  I
    wouldn't be surprised if the CI/BF environments have it set.
    
    Do we know what version of libintl is being used on those BF machines?
    There are some marked differences between some versions, which makes
    this a little more guesswork than it should be.
    
    ---------------------------------------------------------------------
    
    What follows is a walkthrough that just shows that language overrides
    lc_messages and how that can impact things.  No need to read this unless
    you just want more detail.
    
    Assume,
    export LANGUAGE=en_US:en
    export LC_MESSAGES=C.UTF-8
    
    System has catalogs for C.UTF-8 and es.
    
    
    #postgres.conf
    lc_messages = 'C.UTF-8'
    
    InitPostgres calls pg_perm_setlocale with C.UTF-8.
    
    pg_perm_setlocale calls setlocale(LC_MESSAGES, "C.UTF-8") and succeeds.
    
    setlocale uses setenv to set LC_MESSAGES=C.UTF_8
    
    Now assume an error occurs and gettext is called.  A couple of wrappers
    down we get to DCIGETTEXT() with a category of LC_MESSAGES. We call
    guess_category_value with LC_MESSAGES.
    
    guess_category_value implements the priorty as discussed above.  The
    very first thing it checks is getenv("LANGUAGE").  If that is not NULL
    or an empty string it returns whatever is in LANGUAUGE, which in this
    case is en_US:en.
    
    Then back in DCIGETTEXT() we will loop through en_US:en.  We try to find
    the message catalog with 'en_US' first...and fail because we don't have
    that catalog.  Then we loop back and try 'en'...and fail again because
    we don't have that catalog.  One more time through the loop where we
    don't have anything left in our list of languages, so we set the locale
    to 'C'. Then we check that we don't translate if the locale is a single
    C. and we break. Nothing translated.
    
    
    -- 
    Bryan Green
    EDB: https://www.enterprisedb.com