Lokalisierung von Nummern in WordPress anpassen

foto von geralt auf Pixabay
foto von geralt auf pixabay

Ziel der Vorgehensweise ist, beim Formatieren die Anzahl von Dezimalstellen einer Zahl automatisch zu erkennen und in der Ausgabe der Zahlen entsprechend zu berücksichtigen.

Was man in WordPress mit Wörtern oder Datumsangaben machen kann, um sie sprachlichen Gepflogenheiten anzupassen, funktioniert grundsätzlich auch mit der Ausgabe von Zahlen. Als Zahl gilt hierbei zum Beispiel 1000 oder 0.123, nicht jedoch Ziffernfolgen mit Tausender-Trennzeichen, z.B. 1.000 (DE) oder 1,000 (EN), oder wie wir Dezimalzahlen schreiben, mit Kommastellen, wie z.B. 0,54.

Die Funktion number_format_i18n() formatiert Zahlenwerte (die auch Strings sein dürfen, sofern sie ohne Tausendertrennzeichen sind) passend zur Sprache mit einer vorgegebenen Anzahl von Dezimalstellen. Wird keine Dezimalstellenanzahl angegeben, wird auf eine Ganzzahl auf- oder abgerundet. Zudem fügt die Funktion bei entsprechend hohen Zahlen das passende Tausender-Trennzeichen ein.

function number_format_i18n( $number, $decimals = 0 ) {
    global $wp_locale;
 
    if ( isset( $wp_locale ) ) {
        $formatted = number_format( $number, absint( $decimals ), $wp_locale->number_format['decimal_point'], $wp_locale->number_format['thousands_sep'] );
    } else {
        $formatted = number_format( $number, absint( $decimals ) );
    }
 
    /**
     * Filters the number formatted based on the locale.
     *
     * @since 2.8.0
     * @since 4.9.0 The `$number` and `$decimals` parameters were added.
     *
     * @param string $formatted Converted number in string format.
     * @param float  $number    The number to convert based on locale.
     * @param int    $decimals  Precision of the number of decimal places.
     */
    return apply_filters( 'number_format_i18n', $formatted, $number, $decimals );
}

Das funktionert, wenn die Dezimalstellen mit einem Punkt abgegrenzt sind. Der Beistrich in einer Zahl würde ansonsten als Trennzeichen zum nächsten Parameter gesehen der die Anzahl gewünschter Dezimalstellen angibt. Ein Beistrich statt eines Punktes in einem String würde einfach ignoriert. Nachfolgend Beispiele (Ausgabe Deutsch) die funktionieren, und solche, die es nicht tun.

/* funktioniert */
echo number_format_i18n(100000.395); // gibt aus 100.000
echo number_format_i18n(100000.395, 2); // gibt aus 100.000,40
echo number_format_i18n(100000.395, 3); // gibt aus 100.000,395
echo number_format_i18n('100000.395'); // gibt aus 100.000
echo number_format_i18n('100000.395', 2); // gibt aus 100.000,40
echo number_format_i18n('100000.395', 3); // gibt aus 100.000,395

/* funktioniert nicht */
echo number_format_i18n('100000,395', 2); // gibt aus 100.000,00
echo number_format_i18n(100000,395, 2); // gibt aus 100.000,00000... (395 NULLEN)
echo number_format_i18n('100.000,395'); // gibt aus 100
echo number_format_i18n('100.000,395' , 2); // gibt aus 100,00
echo number_format_i18n('100.000,395' , 6); // gibt aus 100,000000

Eine feste Anzahl von Dezimalstellen (inklusive der Darstellung von Nullen, wenn es keine gibt) ist eine tolle Sache, um z.B. Beträge darzustellen. Im technischen Bereich allerdings variiert die Anzahl gewünschter Dezimalstellen gerne mal. Was tun, wenn man beim Anlegen eines Templates oder einer Funktion für die Ausgabe technischer Daten gar nicht weiß, ob und wie viele Dezimalstellen einen erwarten, wenn Ganzzahlen Ganzzahlen bleiben sollen, und nur jene Dezimalstellen sichtbar sein sollen, die angegeben sind, egal allerdings, um wie viele es sich handelt?

Es kommen ja möglicherweise Werte vor wie 0.093, 2.63, 127.8 oder 4795.

Da sich an $decimals = 0 bei Ganzzahlen nichts ändern muss, stellen wir erst mal fest, ob die Zahl Dezimalstellen hat:

function has_decimals( $number) {
    return is_numeric( $number) && floor( $number) != $number;
}

Für die Verwendung im Template für die Datenausgabe schreiben wir dann die Funktion von WordPress unter eigenem Namen ein wenig um.

function specs_number_format_i18n( $number, $decimals = 0 ) {
    global $wp_locale;
    
    if ( has_decimals ( $number ) ) {
        $pieces = explode( '.', $number );
        $decimals = strlen( end( $pieces ) );
    }

    if ( isset( $wp_locale ) ) {
        $formatted = number_format( $number, absint( $decimals ), $wp_locale->number_format['decimal_point'], $wp_locale->number_format['thousands_sep'] );
    } else {
        $formatted = number_format( $number, absint( $decimals ) );
    }
 
    /**
     * Filters the number formatted based on the locale.
     * @param string $formatted Converted number in string format.
     * @param float  $number    The number to convert based on locale.
     * @param int    $decimals  Precision of the number of decimal places.
     */
    return apply_filters( 'specs_number_format_i18n', $formatted, $number, $decimals );
}

Die Voraussetzung dafür, dass das funktioniert ist, dass die ganzen technischen Werte auch wirklich als Zahlen mit Punkt statt Komma und ohne Tausendertrennzeichen erfasst worden sind. Wird der Dezimalparameter angegeben, so wird der Parameter berücksichtigt, und nicht die ermittelte Anzahl von Stellen nach dem Punkt.

Hier ein paar Beispiele:

/* funktioniert */
echo specs_number_format_i18n(100000.395); // gibt aus 100.000,395
echo specs_number_format_i18n(100000.395, 2); // gibt aus 100.000,39
echo specs_number_format_i18n(100000.39); // gibt aus 100.000,39
echo specs_number_format_i18n(100000.3); // gibt aus 100.000,3
echo specs_number_format_i18n(100000); // gibt aus 100.000

/* funktioniert nicht */
echo specs_number_format_i18n('100000,395'); // gibt aus 100.000
echo specs_number_format_i18n(100000,395); // gibt aus 100.000,00000... (395 NULLEN)
...

Bitte Kommentarfunktion nicht für Supportanfragen nutzen. Dem kann hier nicht entsprochen werden. Die Angabe einer E-Mail-Adresse und eines Namens ist nicht erforderlich. Einen (Spitz)-Namen zu nennen wäre aber doch nett.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

Hinweis: Sowohl angegebener Name als auch E-Mail-Adresse (beides ist optional, dafür werden alle Kommentare vor Veröffentlichung geprüft) werden dauerhaft gespeichert. Du kannst jeder Zeit die Löschung Deiner Daten oder / und Kommentare einfordern, direkt über dieses Formular (wird nicht veröffentlicht, und im Anschluss gelöscht), und ich werde das umgehend erledigen. – Mit hinterlassenen Kommentaren hinterlegte IP-Adressen werden nach zwei Monaten automatisch gelöscht

publicly queryable