Search code examples
cmacoslocale

setlocale() has no effect on macOS


I am using the example program for setlocale() from cppreference.com on a macOS 10.14.6 system, however, the output is not localized. I checked that the return value from setlocale() is not NULL and tried a variety of locale specifications in an attempt to get a decimal comma, such as de, de_DE, de_DE.utf8.

Why does this not work?

How can I find out why the output isn't affected, and whether it is because of incorrect locale names?

On the same OS, locale changes from Python do appear to work (as in that they affect number printing by C code running within the same process). Thus I do not think that the problem is that this locale is not supported.


The full program:

#include <stdio.h>
#include <locale.h>
#include <time.h>
#include <wchar.h>
 
int main(void)
{
    // the C locale will be UTF-8 enabled English;
    // decimal dot will be German
    // date and time formatting will be Japanese
    setlocale(LC_ALL, "en_US.UTF-8");
    setlocale(LC_NUMERIC, "de_DE.utf8");
    setlocale(LC_TIME, "ja_JP.utf8");
 
    wchar_t str[100];
    time_t t = time(NULL);
    wcsftime(str, 100, L"%A %c", localtime(&t));
    wprintf(L"Number: %.2f\nDate: %ls\n", 3.14, str);
}

Solution

  • From the terminal, locale -a can be used to see all available locales.

    On my system1, locale -a | grep de_ yields the following results

    de_CH
    de_DE.UTF-8
    de_AT.ISO8859-1
    de_AT.UTF-8
    de_AT.ISO8859-15
    de_DE.ISO8859-15
    de_CH.UTF-8
    de_DE-A.ISO8859-1
    de_CH.ISO8859-15
    de_DE.ISO8859-1
    de_CH.ISO8859-1
    de_AT
    de_DE
    

    setlocale returns NULL in the event that the combination of arguments do not make sense. On my system1,

    #include <stdio.h>
    #include <locale.h>
    #include <time.h>
    #include <wchar.h>
    
    int main(void)
    {
        // the C locale will be UTF-8 enabled English;
        // decimal dot will be German
        // date and time formatting will be Japanese
        char *all = setlocale(LC_ALL, "en_US.UTF-8");
        char *num = setlocale(LC_NUMERIC, "de_DE.utf8");
        char *tim = setlocale(LC_TIME, "ja_JP.utf8");
    
        printf("%s\n%s\n%s\n", all, num, tim);
    
        wchar_t str[100];
        time_t t = time(NULL);
        wcsftime(str, 100, L"%A %c", localtime(&t));
        wprintf(L"Number: %.2f\nDate: %ls\n", 3.14, str);
    }
    

    outputs

    en_US.UTF-8
    (null)
    (null)
    Number: 3.14
    Date: Thursday Thu May 12 08:35:37 2022
    

    Using locales from the prior list

    #include <stdio.h>
    #include <locale.h>
    #include <time.h>
    #include <wchar.h>
    
    int main(void)
    {
        // the C locale will be UTF-8 enabled English;
        // decimal dot will be German
        // date and time formatting will be Japanese
        char *all = setlocale(LC_ALL, "en_US.UTF-8");
        char *num = setlocale(LC_NUMERIC, "de_DE.UTF-8");
        char *tim = setlocale(LC_TIME, "ja_JP.UTF-8");
    
        printf("%s\n%s\n%s\n", all, num, tim);
    
        wchar_t str[100];
        time_t t = time(NULL);
        wcsftime(str, 100, L"%A %c", localtime(&t));
        wprintf(L"Number: %.2f\nDate: %ls\n", 3.14, str);
    }
    

    outputs

    en_US.UTF-8
    de_DE.UTF-8
    ja_JP.UTF-8
    Number: 3,14
    Date: 木曜日 木  5/12 08:37:51 2022
    

    1 Note that this is tested on macOS 10.15.7. Results may differ on macOS 10.14.6. You should not blindly trust examples you find, including mine here, but rather check your own system's locales.

    locale has been available since Mac OS X 10.4.