newlocale(3)

πŸ’– newlocale(3) πŸ’–

okay so bestie, welcome to the Library Functions Manual entry for newlocale(3) β€” yes we're doing locales today, and no it's not scary, i promise 🫢


✨ NAME ✨

newlocale, freelocale β€” create, modify, and free a locale object

πŸŽ€ LIBRARY πŸŽ€

Standard C library (libc, -lc)

🌸 SYNOPSIS 🌸

#include <locale.h>

locale_t newlocale(int category_mask, const char *locale,
                   locale_t base);
void freelocale(locale_t locobj);

πŸ”₯ Feature Test Macro Requirements for glibc (see feature_test_macros(7))

newlocale(), freelocale():

  • Since glibc 2.10:
    • _XOPEN_SOURCE >= 700
  • Before glibc 2.10:
    • _GNU_SOURCE

πŸ’… DESCRIPTION πŸ’…

So, the tea: newlocale() either creates a brand new locale object or modifies an existing one, and it hands you back a reference to that new-or-modified object as the function result. Which one you get is entirely up to the value of base, no cap:

  • If base is (locale_t) 0, you get a new object. fresh out the box, iconic ✨
  • If base refers to a valid existing locale object (like, an object that a previous call to newlocale() or duplocale(3) returned), then that object gets modified by the call. And here's the part you gotta hear me on: if the call succeeds, the contents of base are unspecified β€” which means the object base points at may literally be freed and a whole new object created in its place. so like. the caller needs to stop using base before calling newlocale(), and afterwards should only talk to the modified object through the reference that came back as the function result. if the call fails, though, the contents of base stay valid and unchanged. periodt.

If base is the special locale object LC_GLOBAL_LOCALE (see duplocale(3)), or if it's not (locale_t) 0 and it's not a valid locale object handle β€” the behavior is undefined. πŸ’€ we don't do that.

The category_mask argument is a bit mask that says which locale categories are getting set in a newly created locale object, or modified in an existing one. You build the mask by bitwise-ORing these constants together:

LC_ADDRESS_MASK, LC_CTYPE_MASK, LC_COLLATE_MASK, LC_IDENTIFICATION_MASK, LC_MEASUREMENT_MASK, LC_MESSAGES_MASK, LC_MONETARY_MASK, LC_NUMERIC_MASK, LC_NAME_MASK, LC_PAPER_MASK, LC_TELEPHONE_MASK, and LC_TIME_MASK.

Or, alternative vibe: you can just pass LC_ALL_MASK, which is equivalent to ORing every single one of those constants above. so much easier, iykyk.

For every category you name in category_mask, the locale data gets pulled from locale and used in the object returned by newlocale(). And if a new locale object is being created, then all the categories you didn't put in category_mask get their data from the default ("POSIX") locale.

These preset values of locale are defined for all the categories you can stick in category_mask:

  • "POSIX" β€” a minimal locale environment for C language programs. the bare minimum, humble but reliable.
  • "C" β€” equivalent to "POSIX". same energy, different name 🫢
  • "" β€” an implementation-defined native environment corresponding to the values of the LC_* and LANG environment variables (see locale(7)). yes it's literally an empty string, and yes it means something. the way environment variables just be deciding your fate.

🌈 freelocale()

freelocale() deallocates the resources associated with locobj β€” which is a locale object that a previous call to newlocale() or duplocale(3) returned. If locobj is LC_GLOBAL_LOCALE, or if it's not a valid locale object handle, the results are undefined. πŸ™ˆ

And once a locale object has been freed, the program should make no further use of it. like, at all. don't text back, don't look at its story. it's gone.


⭐ RETURN VALUE ⭐

On success, newlocale() returns a handle that you can use in calls to duplocale(3), freelocale(), and other functions that take a locale_t argument. πŸŽ‰

On error, newlocale() returns (locale_t) 0, and sets errno to indicate the error. that's your cue that something went sideways.


πŸ’œ ERRORS πŸ’œ

  • EINVAL β€” one or more bits in category_mask do not correspond to a valid locale category.
  • EINVAL β€” locale is NULL.
  • ENOENT β€” locale is not a string pointer referring to a valid locale.
  • ENOMEM β€” insufficient memory to create a locale object. bestie is broke, no object for you.

πŸ‘‘ STANDARDS πŸ‘‘

POSIX.1-2008.

πŸ¦‹ HISTORY πŸ¦‹

glibc 2.3.

πŸ“ NOTES πŸ“

Every locale object created by newlocale() should be deallocated using freelocale(). clean up after yourself, main character energy ✨


🌟 EXAMPLES 🌟

Okay so this program takes up to two command-line arguments, and each one identifies a locale. The first argument is required, and it's the one used to set the LC_NUMERIC category in a locale object created with newlocale(). The second command-line argument is optional; if it's there, it sets the LC_TIME category of the locale object.

Once the locale object is created and initialized, the program applies it with uselocale(3), and then tests the effect of the locale changes by:

  1. Displaying a floating-point number with a fractional part. This output will be affected by the LC_NUMERIC setting. In many European-language locales, the fractional part of the number is separated from the integer part using a comma, rather than a period.
  2. Displaying the date. The format and language of the output will be affected by the LC_TIME setting.

Here are some example runs of this program, shell session style πŸ’…

Set the LC_NUMERIC category to fr_FR (French):

$ ./a.out fr_FR;
123456,789
Fri Mar  7 00:25:08 2014

Set the LC_NUMERIC category to fr_FR (French), and the LC_TIME category to it_IT (Italian):

$ ./a.out fr_FR it_IT;
123456,789
ven 07 mar 2014 00:26:01 CET

Specify the LC_TIME setting as an empty string, which causes the value to be taken from environment variable settings (which, here, specify mi_NZ, New Zealand Māori):

$ LC_ALL=mi_NZ ./a.out fr_FR ""
123456,789
Te Paraire, te 07 o PoutΕ«-te-rangi, 2014 00:38:44 CET

🌸 Program source 🌸

#define _XOPEN_SOURCE 700
#include <err.h>
#include <locale.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int
main(int argc, char *argv[])
{
    char buf[100];
    time_t t;
    size_t s;
    struct tm *tm;
    locale_t loc, nloc;

    if (argc < 2) {
        fprintf(stderr, "Usage: %s locale1 [locale2]\n", argv[0]);
        exit(EXIT_FAILURE);
    }

    /* Create a new locale object, taking the LC_NUMERIC settings
       from the locale specified in argv[1].  */

    loc = newlocale(LC_NUMERIC_MASK, argv[1], (locale_t) 0);
    if (loc == (locale_t) 0)
        err(EXIT_FAILURE, "newlocale");

    /* If a second command-line argument was specified, modify the
       locale object to take the LC_TIME settings from the locale
       specified in argv[2].  We assign the result of this newlocale()
       call to 'nloc' rather than 'loc', since in some cases, we might
       want to preserve 'loc' if this call fails.  */

    if (argc > 2) {
        nloc = newlocale(LC_TIME_MASK, argv[2], loc);
        if (nloc == (locale_t) 0)
            err(EXIT_FAILURE, "newlocale");
        loc = nloc;
    }

    /* Apply the newly created locale to this thread.  */

    uselocale(loc);

    /* Test effect of LC_NUMERIC.  */

    printf("%8.3f\n", 123456.789);

    /* Test effect of LC_TIME.  */

    t = time(NULL);
    tm = localtime(&t);
    if (tm == NULL)
        err(EXIT_FAILURE, "time");

    s = strftime(buf, sizeof(buf), "%c", tm);
    if (s == 0)
        err(EXIT_FAILURE, "strftime");

    printf("%s\n", buf);

    /* Free the locale object.  */

    uselocale(LC_GLOBAL_LOCALE);    /* So 'loc' is no longer in use */
    freelocale(loc);

    exit(EXIT_SUCCESS);
}

🌈 SEE ALSO 🌈

locale(1), duplocale(3), setlocale(3), uselocale(3), locale(5), locale(7)


okay that's the whole page bestie, you ate that 🫢 this was Linux man-pages 6.20, dated 2026-02-08, and it's the newlocale(3) girlies' moment πŸ’– mwah, go write some locales, slay πŸ’…βœ¨

πŸ“¦ where this page comes from
  • arch rolling: man-pages 6.20-1 Β· BSD-2-Clause AND BSD-3-Clause AND BSD-4.3TAHOE AND BSD-4-Clause-UC AND GPL-1.0-or-later AND GPL-2.0-only AND GPL-2.0-or-later AND GPL-3.0-or-later AND LGPL-3.0-linking-exception AND LGPL-3.0-or-later AND LicenseRef-Public-Domain AND LicenseRef-UltraPermissive AND Linux-man-pages-1-para AND Linux-man-pages-copyleft AND Linux-man-pages-copyleft-2-para AND Linux-man-pages-copyleft-var AND MIT AND Spencer-94
  • nixpkgs unstable: man-pages 6.20
  • πŸ“œ the page's license: Linux-man-pages-copyleft
  • πŸ’– girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms