Navigation
 Startseite
 Fachbücher
 Anzeigenmarkt
 Forum
 Webmaster News
 Script Newsletter
 Push Meldungen
 Kontakt
 Script Installation
 Php
 Php Tutorials
 Lernpfade
 Webhoster Vergleich
 Impressum

Community-Bereich
 kostenlos Registrieren
 Anmelden
 Benutzerliste

Script Datenbank
 Script Archiv
 Script Top 20
 Screenshots
 Testberichte

Suche
 

Unsere Php Scripts
 Counter Script
 Umfrage Script
 Bilder Upload Script
 Terminverwaltung
 Simple PHP Forum
 RSS Grabber

Tools und Generatoren
 .htpasswd Generator
 md5 Generator
 base64 Generator
 Markdown to HTML
 Colorpicker
 Unix timestamp Tool
 Unit Test Generator
 TLD Liste
 Webkatalog‑Verzeichnis

Webspace-Mieten.d...
Webhosting mit Plesk aus Erfurt: Vier...
https://www.Webspace-Mieten.de
Artfiles.de
Bietet Serviceorientierte...
https://www.Artfiles.de
 
 
 

PHP setlocale() Function: Locale setzen und abfragen

Sie befinden sich: Home > Php Tutorial > PHP setlocale() Function: L...

PHP setlocale() Function: Locale setzen und abfragen
Veröffentlicht am:
28.10.2026
Hits / Besucher:
9
Sprache:
  Deutsch
Tutorial Art:
eigenes
Eingetragen von:
Merkliste:
 
Beschreibung

Eine Mitgliederliste sortiert „Özdemir“ hinter „Zander“, und ein CSV-Export schreibt seit dem Einbinden einer neuen Bibliothek Kommas in die Preisspalte. Beides hängt an derselben Einstellung, der Locale des PHP-Prozesses. Wie man Datum, Zahlen und Währungen je Sprache ausgibt, zeigen datefmt_create() und numfmt_create(). Darunter liegt die Einstellung, die PHP setlocale() umstellt und die einige ältere Funktionen still mitlesen.

Illustration zum Tutorial: PHP setlocale() Function: Locale setzen und abfragen

Seit PHP 8 sind das nur noch wenige Funktionen. Und der Name, der unter Windows funktioniert, liefert unter Linux häufig nur false.

Was PHP setlocale() macht

PHP setlocale() bekommt eine Kategorie und einen oder mehrere Namen. Sie probiert die Namen der Reihe nach, stellt die Kategorie auf den ersten um, den das Betriebssystem kennt, und gibt diesen Namen zurück. Kennt das System keinen davon, kommt false, und die bisherige Einstellung bleibt unverändert. Locales sind nämlich kein Teil von PHP, sondern Dateien des Betriebssystems. Deshalb gehört die Prüfung des Rückgabewerts in jeden Aufruf:

<?php

$locale = setlocale(LC_ALL, [
'de_DE.UTF-8', /* Linux */
'de_DE.utf8',
'de-DE.UTF-8', /* Windows 10 und neuer */
]);

if ($locale === false) {
error_log('Keine deutsche UTF-8-Locale');
} else {
echo $locale; /* z. B. de_DE.UTF-8 */
}

Mit installierter deutscher Locale antwortete Linux mit de_DE.UTF-8, Windows mit de-DE.UTF-8. Der Ablauf eines Aufrufs von PHP setlocale() sieht so aus:

flowchart TD
    A[setlocale mit Kategorie und Namen]
    B{Name auf dem System vorhanden?}
    C{weitere Namen in der Liste?}
    D[false, nichts geändert]
    E[Kategorie umstellen]
    F[Namen zurückgeben]
    G[gilt im ganzen Prozess]
    H[Requestende: zurück zum Start]
    A --> B
    B -->|ja| E
    E --> F
    F --> G
    G --> H
    B -->|nein| C
    C -->|ja| B
    C -->|nein| D

Die Signatur im Original

Das Handbuch führt zwei Schreibweisen, einmal mit einzelnen Namen und einmal mit einem Array:

setlocale(

int $category,
string $locales,
string ...$rest
): string|false

setlocale(
int $category,
array $locale_array
): string|false

/* Set locale information.
$category LC_ALL, LC_COLLATE, LC_CTYPE,
LC_MONETARY, LC_NUMERIC, LC_TIME,
LC_MESSAGES (not on Windows)
$locales locale name; further names or an
array are tried in order
"" = locale from the environment
"0" = return the current setting
returns the new current locale, or false */

Der String '0' ändert nichts und liefert nur die aktuelle Einstellung. Der leere String übernimmt die Locale aus der Umgebung, unter Linux aus Variablen wie LANG, unter Windows aus den Regionseinstellungen. Ohne diesen Aufruf startet PHP mit der Locale C, auch wenn LANG=de_DE.UTF-8 gesetzt ist.

Die LC-Kategorien und was sie steuern

LC_ALL stellt alle auf einmal um. Wer gezielter arbeitet, ändert nur die eine, die er braucht:

Kategorie Wirkt in PHP 8 auf Gemessen mit deutscher Locale
LC_NUMERIC printf() und sprintf() mit %f, %g und %G, localeconv() 1234,50 statt 1234.50
LC_COLLATE strcoll(), sort() mit SORT_LOCALE_STRING Äpfel vor Birne statt hinter Zitrone
LC_CTYPE Zeichenklassen in ctype_alpha() und Co., iconv() mit Umschrift, escapeshellarg() aus Ärger wird AErger
LC_MONETARY Währungsangaben in localeconv() €, zwei Nachkommastellen
LC_TIME strftime(), seit PHP 8.1 abgekündigt Sonntag statt Sunday
LC_MESSAGES Systemmeldungen und gettext, nur unter Linux unter Windows nicht definiert

Die Konstanten tragen je nach System andere Zahlen. Unter Linux ist LC_ALL die 6, unter Windows die 0, und LC_MESSAGES führt unter Windows zu Error: Undefined constant "LC_MESSAGES". Zahlen statt Namen stellen auf dem anderen System eine falsche Kategorie um.

Locale abfragen und Namen unter Linux und Windows

Zum Abfragen dient der String '0'. Unter Linux kommt dabei schon beim Start ein langer Sammelstring heraus, weil PHP die Zeichenklassen selbst auf C.UTF-8 stellt. Eine häufige Abkürzung ist dagegen falsch:

<?php

echo setlocale(LC_ALL, '0');
/* Linux: LC_CTYPE=C.UTF-8;LC_NUMERIC=C;...
Windows: C */

setlocale(LC_ALL, null);
/* fragt NICHT ab, sondern setzt die Locale
aus der Umgebung, unter Windows etwa
German_Germany.1252 */

Der Wert null wirkt wie der leere String. Im Linux-Container fiel LC_CTYPE dadurch von C.UTF-8 auf C, und escapeshellarg('Äpfel') lieferte danach nur noch 'pfel'. Ein Locale-Name besteht aus dem Sprachkürzel nach ISO 639 (de), dem Ländercode (DE) und dem Zeichensatz (UTF-8). Linux verbindet Sprache und Land mit einem Unterstrich, Windows schreibt sie wie ein Sprach-Tag nach BCP 47 mit Bindestrich:

Name Windows Linux, Docker-Image Linux mit locale-gen
de_DE.UTF-8 false false gesetzt
de-DE.UTF-8 gesetzt false false
de-DE, German gesetzt, Codepage 1252 false nur mit zusätzlich erzeugtem Latin-1, sonst false
de_DE false false nur mit zusätzlich erzeugtem Latin-1, sonst false
C.UTF-8 false gesetzt gesetzt
erfunden: de-XX, zz gesetzt false false

Die letzte Zeile ist die unangenehmste. Windows quittiert jedes formal gültige Sprachkürzel mit Erfolg, auch eines, das es nicht gibt. Ein Rückgabewert ungleich false beweist dort wenig. Außerdem gehören nur UTF-8-Namen in die Kandidatenliste: Mit de-DE und damit Codepage 1252 sortierte Windows eine Liste aus UTF-8-Wörtern falsch, mit de-DE.UTF-8 richtig. Unter Linux lieferte localeconv() mit Latin-1 zudem EUR statt des Euro-Zeichens, unter Windows mit Codepage 1252 das einzelne Byte 0x80.

Wenn PHP setlocale() false liefert

Meist fehlt die gewünschte Locale auf dem Server. Welche vorhanden sind, verrät unter Linux der Befehl locale -a. Im offiziellen PHP-Image, das auf Debian aufsetzt, stehen dort nur C, C.utf8 und POSIX. Jeder deutsche Name scheitert also, und sortiert wird stillschweigend weiter nach Bytes. Im eigenen Image lässt sich das nachholen:

RUN apt-get update \

&& apt-get install -y locales \
&& echo "de_DE.UTF-8 UTF-8" >> /etc/locale.gen \
&& locale-gen

Danach stand de_DE.utf8 in der Liste, und PHP setlocale() lieferte für de_DE.UTF-8 den Namen statt false. Auf Shared Hosting bleibt nur locale -a per SSH oder eine Anfrage beim Anbieter.

Was die Locale in PHP 8 noch beeinflusst

Ein Test mit deutscher LC_NUMERIC zeigt, wo die Grenze verläuft:

<?php

setlocale(LC_NUMERIC, ['de_DE.UTF-8', 'de-DE.UTF-8']);

echo sprintf('%.2f', 19.99); /* 19,99 */
echo sprintf('%.2F', 19.99); /* 19.99 */
echo 19.99; /* 19.99 */
echo number_format(19.99, 2); /* 19.99 */
var_dump((float) '19,99'); /* float(19) */

Von den Platzhaltern folgen %f, %g und %G der Locale, das große %F und %e nie. Die Ausgabe einer Zahl mit echo nimmt seit PHP 8.0 immer den Punkt, und eine Formulareingabe mit Komma liest auch eine deutsche Locale nicht als Zahl. Daten aus $_POST bleiben von PHP setlocale() also unberührt. Weitere gemessene Fälle:

  • Folgt der Locale: localeconv(), strcoll(), sort() mit SORT_LOCALE_STRING, ctype_alpha() bei 8-Bit-Daten, unter Linux iconv() mit //TRANSLIT und escapeshellarg().
  • Folgt ihr nicht: date() bleibt englisch, number_format() und json_encode() nehmen den Punkt, strtoupper(), strtolower() und ucfirst() arbeiten seit PHP 8.2 nur noch mit ASCII.

Das Tutorial zu strtoupper() und mb_strtoupper() zeigt, warum für Umlaute ohnehin die mb-Funktionen zuständig sind.

Praxis: deutsch sortieren und Zahlen mit localeconv()

Der sinnvollste Einsatz von PHP setlocale() ist eine Sortierung nach deutscher Gewohnheit. Damit die Einstellung keine anderen Programmteile trifft, wird sie vorher gesichert und danach zurückgesetzt:

<?php

$obst = ['Zitrone', 'Äpfel', 'apfel', 'Birne',
'Öl', 'Ofen', 'Zebra', 'äpfel'];

$alt = setlocale(LC_ALL, '0');
setlocale(LC_COLLATE, ['de_DE.UTF-8', 'de-DE.UTF-8']);
sort($obst, SORT_LOCALE_STRING);
setlocale(LC_ALL, $alt);

echo implode(', ', $obst);
/* apfel, äpfel, Äpfel, Birne, Ofen, Öl,
Zebra, Zitrone
ohne Locale: Birne, Ofen, Zebra, Zitrone,
apfel, Äpfel, Öl, äpfel */

Für Zahlen liefert localeconv() die Trennzeichen der aktuellen Locale, die number_format() dann ausdrücklich übergeben bekommt:

<?php

setlocale(LC_NUMERIC, ['de_DE.UTF-8', 'de-DE.UTF-8']);
$lc = localeconv();

echo number_format(
1234567.891,
2,
$lc['decimal_point'],
$lc['thousands_sep']
); /* 1.234.567,89 */

Spürbar wirkt die Locale auch bei der Umschrift für sprechende URLs:

<?php

setlocale(LC_CTYPE, ['de_DE.UTF-8', 'C.UTF-8']);
$ascii = iconv(
'UTF-8',
'ASCII//TRANSLIT',
'Ärger über Café'
);
echo $ascii;
/* de_DE.UTF-8: AErger ueber Cafe
C.UTF-8: Arger uber Cafe
C: ?rger ?ber Caf? */

Unter Linux entscheidet LC_CTYPE also, ob aus einem Umlaut zwei Buchstaben, einer oder ein Fragezeichen werden. Unter Windows hängt das Ergebnis nicht von der Locale ab.

Prozess und Request: wie weit PHP setlocale() reicht

Die Einstellung gilt nicht nur für ein Skript, sondern für den ganzen PHP-Prozess. Ruft eine eingebundene Bibliothek PHP setlocale() auf, trifft das jeden Code, der danach läuft. Derselbe Mechanismus, der in der Einleitung die Preisspalte des CSV-Exports verdorben hat, trifft hier eine SQL-Anweisung:

<?php

function pdfErzeugen(): void
{
setlocale(LC_ALL, ['de_DE.UTF-8', 'de-DE.UTF-8']);
/* ... */
}

pdfErzeugen();
$sql = sprintf(
'UPDATE artikel SET preis = %f',
19.99
);
echo $sql;
/* UPDATE artikel SET preis = 19,990000 */

Das ist ein Syntaxfehler in der Datenbank. Für Maschinenformate gehört deshalb %F in den Formatstring, und Werte für SQL laufen besser über Prepared Statements.

Über das Ende des Requests hinaus wandert die Locale dagegen nicht. Unter Apache mit mod_php und unter dem eingebauten Server php -S setzte ein Request de_DE.UTF-8, und der nächste Request im selben Prozess begann wieder mit dem Ausgangszustand, also C mit Zeichenklassen in C.UTF-8. PHP setzt die Locale beim Requestende zurück. Anders sieht es bei Server-APIs aus, die mehrere Threads in einem Prozess betreiben: Laut Handbuch teilen sich dort alle Threads die Locale, und ein paralleles Skript kann sie mitten im Lauf ändern. Unter Windows trennt PHP die Einstellung seit Version 7.0.5 je Thread.

setlocale() oder intl?

Für neuen Code ist die intl-Erweiterung meist die bessere Wahl. Sie bringt eigene Sprachdaten mit und braucht keine Locale des Betriebssystems. Das zeigt ein Docker-Image ohne deutsche Locale:

<?php

var_dump(setlocale(LC_ALL, 'de_DE.UTF-8'));
/* bool(false), keine Locale im Image */

$fmt = new NumberFormatter(
'de_DE',
NumberFormatter::CURRENCY
);
echo $fmt->formatCurrency(1234.5, 'EUR');
/* 1.234,50 €, mit geschütztem Leerzeichen */

Ein Formatierer trägt seine Sprache selbst, wenn man sie im Konstruktor übergibt. Der Standardwert Locale::getDefault() hängt dagegen am Prozess, denn ICU liest ihn beim ersten Zugriff einmal aus der Locale. Lief vorher setlocale(LC_ALL, 'de_DE.UTF-8'), meldete er de_DE, und zwar auch in allen folgenden Requests desselben Prozesses, sonst blieb er bei en_US_POSIX. Für Zahlen und Währungen ist numfmt_create() der Weg, für Datumsangaben datefmt_create(), und wie der Collator Listen ohne Betriebssystem-Locale sortiert, zeigt der Artikel über das Sortieren von Arrays. Die Locale des Prozesses bleibt für Altfunktionen und Bibliotheken, die sie lesen.

PHP setlocale() von 8.0 bis 8.5

Wer älteren Code aktualisiert, stößt auf diese Änderungen:

Version Änderung
8.0 Fließkommazahlen werden ohne Rücksicht auf die Locale in Text umgewandelt
8.1 strftime() ist abgekündigt. Bis 8.3 lautet die Meldung Function strftime() is deprecated, ab 8.4 mit dem Zusatz since 8.1, use IntlDateFormatter::format() instead
8.2 Groß- und Kleinschreibung mit strtolower() und Verwandten nur noch für ASCII
8.5 die Zahl 0 als zweiter Parameter wirft mit strict_types einen TypeError

Das Handbuch beschreibt die letzte Zeile allgemeiner. Unter PHP 8.5.8 trat der Fehler nur mit declare(strict_types=1) auf, ohne diese Angabe kam weiter die Abfrage:

<?php

declare(strict_types=1);

setlocale(LC_ALL, 0);
/* PHP 8.5: TypeError: setlocale(): Argument
#2 ($locales) must be of type
array|string|null, int given */

setlocale(LC_ALL, '0'); /* in jeder Version */

Fazit

Von der einst umfassenden Sprachumstellung ist bei PHP setlocale() nicht viel geblieben. Sie steuert das Dezimalkomma in printf(), die Sortierung mit SORT_LOCALE_STRING, die Zeichenklassen und unter Linux die Umschrift von iconv(). Datum, Zahlausgabe mit echo und Großschreibung liegen außerhalb ihrer Reichweite.

Praktisch heißt das: nur UTF-8-Namen in die Kandidatenliste, den Rückgabewert immer prüfen, im Container die Locale nachinstallieren und mit '0' abfragen, nie mit null. Weil die Einstellung den ganzen Prozess trifft, wird sie für einen Block gesichert und danach zurückgesetzt. Für Datum, Zahlen und Währungen in neuem Code ist intl der verlässlichere Weg.

 

Tags:

 

 

Kommentare (0)

Noch keine Kommentare. Sei der Erste!

Melde dich an, um einen Kommentar zu schreiben.
Bücherregal mit drei Büchern: 'PHP 4 - Grundlagen und Profiwissen' von Hanser Verlag, 'Webdesign in a Nutshell' von O'Reilly Verlag, und 'Webgestaltung' von Galileo Computing.