The <locale.h> header controls locale—the cultural rules for formatting numbers, money, dates, and sorting text. With setlocale and localeconv, your program can follow the user’s regional settings instead of always using the plain "C" locale.
01
setlocale
Set/query.
02
LC_ALL
Everything.
03
LC_NUMERIC
Numbers.
04
localeconv
lconv info.
05
"C"
Default.
06
LC_TIME
Dates.
Fundamentals
Definition and Usage
A locale bundles conventions: which character is the decimal point, how dates are written, how strings sort, and how ctype classifies letters. At startup, C programs use the "C" locale unless you call setlocale.
setlocale(int category, const char *locale) changes one category or all of them. Pass NULL as the second argument to query the current setting without changing it. On success it returns a string naming the locale; on failure it returns NULL.
💡
Beginner Tip
The old reference used printf("%'f", ...) for thousands separators—that is a GNU extension, not standard C. Use localeconv() for portable formatting, or document that your program requires GNU libc.
Foundation
📝 Syntax
Include the header:
C
#include <locale.h>
Category macros
LC_ALL — all categories together.
LC_COLLATE — string collation (strcoll, strxfrm).
LC_CTYPE — character classification (isalpha, toupper).
LC_MONETARY — currency formatting.
LC_NUMERIC — decimal point and thousands separator for numbers.
Compile with gcc file.c -std=c11 -o out. Locale names and output vary by OS. Examples use "C" where portability matters; regional locales may need to be installed on your system.
📚 Getting Started
Read formatting rules and set locale safely.
Example 1 — Read Formatting with localeconv
Portable replacement for the reference example—no GNU %'f extension.
C
#include <locale.h>
#include <stdio.h>
int main(void) {
const struct lconv *lc;
if (setlocale(LC_ALL, "C") == NULL) {
printf("Failed to set C locale\n");
return 1;
}
lc = localeconv();
printf("Decimal point: '%s'\n", lc->decimal_point);
printf("Thousands sep: '%s'\n",
lc->thousands_sep[0] ? lc->thousands_sep : "(none)");
/* printf uses locale for some conversions; C locale uses '.' */
printf("Number: %.2f\n", 1234567.89);
return 0;
}
localeconv returns pointers to strings describing separators. In the "C" locale the decimal point is . and there is no thousands separator. Standard printf does not insert thousands commas without extensions.
Example 2 — Always Check setlocale Return Value
Trying an unavailable locale must not be ignored.
C
#include <locale.h>
#include <stdio.h>
int main(void) {
char *result = setlocale(LC_ALL, "xx_YY.UTF-8");
if (result == NULL) {
printf("Locale not available — falling back to C\n");
setlocale(LC_ALL, "C");
} else {
printf("Locale set to: %s\n", result);
}
printf("Current locale: %s\n", setlocale(LC_ALL, NULL));
return 0;
}
📤 Output:
Locale not available — falling back to C
Current locale: C
How It Works
setlocale returns NULL when the requested locale is not installed. Fall back to "C" for predictable behavior. Use setlocale(LC_ALL, NULL) to read the active locale name.
📈 Practical Patterns
Change one category, format dates, and restore settings.
Example 3 — Change Only LC_NUMERIC
Adjust number formatting without affecting date or collation settings.
C
#include <locale.h>
#include <stdio.h>
int main(void) {
setlocale(LC_ALL, "C");
printf("C locale: %.2f\n", 3.14);
if (setlocale(LC_NUMERIC, "en_US.UTF-8") != NULL) {
printf("en_US numeric: %.2f\n", 3.14);
printf("Decimal point: %s\n", localeconv()->decimal_point);
} else {
printf("en_US.UTF-8 not installed on this system\n");
}
return 0;
}
📤 Output (if en_US.UTF-8 installed):
C locale: 3.14
en_US numeric: 3.14
Decimal point: .
How It Works
LC_NUMERIC limits the change to number formatting. Some European locales use , as the decimal separator—try de_DE.UTF-8 on Linux if installed to see 3,14 style output from printf.
LC_TIME=C: Sunday, 05 July 2026
LC_TIME=en_US.UTF-8: Sunday, 05 July 2026
How It Works
strftime with %A (weekday) and %B (month) uses LC_TIME. In locales like de_DE.UTF-8, month and day names appear in German. Output depends on installed locales and the current date.
Example 5 — Save and Restore Locale
Temporarily switch locale, then put it back to avoid surprising other code.
Before: C
During: C (printing 1.50)
After restore: C
How It Works
Save the locale name before changing it. Libraries and other modules may assume the original locale. Copy the string because subsequent setlocale calls may invalidate the old pointer.
Applications
🚀 Common Use Cases
Desktop utilities — setlocale(LC_ALL, "") to match the user’s OS settings.
Report generators — locale-aware dates with strftime and LC_TIME.
Financial output — localeconv currency fields for invoices.
Sorting names — LC_COLLATE with strcoll for dictionary order.
Parsers — read decimal_point before parsing user numbers.
Servers — keep "C" locale for logs; localize only UI layers.
🧠 How locale.h Works
1
Choose category
LC_ALL for everything, or LC_NUMERIC / LC_TIME alone.
Category
2
Call setlocale
Pass locale name or "" for environment. Check for NULL.
Activate
3
Library functions adapt
printf, strftime, isalpha, strcoll follow the locale.
Effect
=
💬
Localized output
Numbers, dates, and sort order match regional expectations.
Important
📝 Notes
Programs start in the "C" locale unless the environment or your code changes it.
Locale names are platform-specific; en_US.UTF-8 on Linux may differ on Windows (English_United States.utf8).
setlocale is not thread-safe—avoid changing locale in multithreaded servers casually.
localeconv returns a static struct; copy strings if you call setlocale again.
Changing LC_CTYPE affects <ctype.h> functions for non-ASCII letters.
For full Unicode/i18n, many projects use ICU or similar libraries beyond standard C.
Performance
⚡ Optimization
Keep the default "C" locale in performance-critical paths. Locale-aware collation and formatting are slower than byte-wise compares and fixed printf formats. Change locale only at UI boundaries or when generating user-facing output.
Wrap Up
Conclusion
<locale.h> lets C programs respect cultural conventions for numbers, money, dates, and text ordering. Use setlocale with care, check return values, and read details with localeconv.
For predictable behavior in libraries and servers, default to "C". For user-facing apps, setlocale(LC_ALL, "") picks up the environment—when that locale is available.
Use LC_NUMERIC / LC_TIME when you need only one category
Use localeconv for portable separator characters
Keep servers and libraries on "C" unless required
❌ Don’t
Assume %'f works outside GNU systems
Change locale in one thread without protecting others
Ignore failed setlocale calls
Store pointers from localeconv across setlocale calls
Assume every locale name works on every OS
Summary
Key Takeaways
Knowledge Unlocked
Five things to remember about locale.h
Localization in C, explained simply.
5
Core concepts
💬01
setlocale
Change/query.
Core API
📚02
"C"
Portable.
Default
📈03
localeconv
Separators.
lconv
📄04
LC_*
Categories.
Granular
🌐05
Threads
Not safe.
Caution
❓ Frequently Asked Questions
locale.h provides setlocale() to change or query cultural conventions (number format, date format, collation, character classes) and localeconv() to read numeric and monetary formatting details. It helps programs adapt output to a region or language.
It sets the entire locale from environment variables such as LANG and LC_* (e.g. LC_NUMERIC). An empty string means 'use the user's environment.' On success it returns a locale name string; on failure it returns NULL.
The default portable locale, often selected with setlocale(LC_ALL, "C"). Numbers use a dot as the decimal point, sorting is byte-based, and behavior is predictable across platforms. Programs start in the C locale unless changed.
No. setlocale modifies global locale state and is not thread-safe in standard C. Multithreaded programs should avoid changing locale in one thread while others use locale-sensitive functions, or use platform-specific per-thread locale APIs.
localeconv() returns a pointer to struct lconv with fields like decimal_point, thousands_sep, currency_symbol, and grouping rules for the current locale. The structure is static—copy strings if you need them after another locale change.
The ' flag in %'f is a GNU extension, not standard C. Portable code should read thousands_sep from localeconv() and format numbers manually, or use higher-level libraries. Do not rely on %'f for cross-platform programs.
Did you know?
The "C" locale is not “American English”—it is a minimal, portable convention designed for consistent program behavior. Real-world localization often needs installed OS locale data, and embedded systems may only support "C". That is why robust apps check setlocale and ship fallbacks.