# locale.h **`locale.h`** controls how your program formats and interprets culture-specific data: whether the decimal separator is `.` or `,`, what the currency symbol is, which characters count as letters. By default a C program runs in the `"C"` locale — ASCII, `.` decimal separator, no localisation — which is predictable but not what a German or French user expects to see. ```c #include setlocale(LC_ALL, ""); // pick up the user's environment locale setlocale(LC_ALL, "C"); // reset to the predictable ASCII baseline setlocale(LC_NUMERIC, "de_DE.UTF-8"); // German number format only ``` The category lets you change one aspect without touching the others: | Category | Controls | | `LC_ALL` | Everything | | `LC_NUMERIC` | Decimal point, thousands separator | | `LC_MONETARY` | Currency symbol and format | | `LC_CTYPE` | `isalpha`, `toupper` etc. | | `LC_COLLATE` | String comparison order | | `LC_TIME` | `strftime` output | `localeconv()` returns a `struct lconv` with all the current locale's formatting strings: `decimal_point`, `thousands_sep`, `currency_symbol`, and more. The practical rule: call `setlocale(LC_ALL, "")` at startup if you are producing output for humans. But be careful with `LC_NUMERIC` — any library that calls `setlocale` on your behalf can change the decimal separator under your feet, which will break `strtod` parsing of machine-generated data. Keep `LC_NUMERIC` as `"C"` when parsing programmatic input. ## Practice ```c // compile: gcc -o localedemo localedemo.c // run: ./localedemo // description: show how locale changes decimal formatting; install de_DE if missing #include #include int main(void) { double pi = 3.141592653589793; setlocale(LC_ALL, "C"); printf("C locale: %f\n", pi); // 3.141593 if (!setlocale(LC_NUMERIC, "de_DE.UTF-8") && !setlocale(LC_NUMERIC, "de_DE")) puts("de_DE locale not available; install with: sudo locale-gen de_DE.UTF-8"); else { printf("de_DE locale: %f\n", pi); // 3,141593 (comma!) printf("decimal_point = '%s'\n", localeconv()->decimal_point); } return 0; } ``` If the German locale is installed you will see a comma instead of a dot in the second line. If not, install it with `sudo locale-gen de_DE.UTF-8` on Debian/Ubuntu. Once you have seen this in action it is hard to forget that `LC_NUMERIC` can silently change how `printf` and `strtod` work.