# Normalisierung und Lokalisierung

`Zend_Locale_Format` ist eine interne Komponente welche von `Zend_Locale` verwendet wird. Alle lokalisierbaren Klassen benutzen `Zend_Locale_Format` für Normalisierung und Lokalisierung von Nummern und Daten. Normalisierung beinhaltet das Analysieren von Eingaben von einer Vielfalt von Werten wie Datumswerte in eine standardisierten, strukturieren Art wie zum Beispiel ein PHP Array mit Jahr, Monat und Tages Elementen.

Genau die gleiche Zeichenkette die eine Zahl oder ein Datum enthält meint etwas ganz anderes für Leute mit anderen Regeln und Konventionen. Die Erkennung von Nummern und Daten benötigt Regeln darüber wie diese Zeichenketten zu interpretieren sind um diese Werte in eine standardisierte Form zu bringen. Deswegen benötigen alle Methoden in `Zend_Locale_Format` ein Gebietsschema um Eingabedaten analysieren zu können.

## Standard "root" Gebietsschema

Wenn kein Gebietsschema spezifiziert wurde, wird die Normalisierung und Lokalisierung das Standard "root" Gebietsschema verwenden, was zu unerwarteten Ergebnissen führen kann wenn die Eingabe in einem anderen Gebietsschema angegeben oder die Ausgabe für ein anderes Gebietsschema erwartet wurde.

## Normalisierung von Nummern: getNumber($input, Array $options)

Es gibt viele Ziffernsysteme welche siche vom üblichen Dezimalsystem unterscheiden (z.B. "3.14"). Nummern können mit der Funktion `getNumber()` normalisiert werden um ein gleichwertiges Ergebnis in einer Schreibweise des Standard Dezimalsystems zu erhalten. Für alle Ziffern-Relevanten Diskussionen in diesem Handbuch werden die Arabisch/Europäischen Ziffern (0,1,2,3,4,5,6,7,8,9) verwendet, ausser es ist anders definiert. Das Options Array kann ein 'locale' Gebietsschema enthalten, um eine Gruppierung und Kommazeichen zu definieren. Das Array kann auch eine Genauigkeit 'precision' enthalten um überschüssige Ziffern vom Ergebnis abzuschneiden.

### Normalisieren von Nummern

    $locale = new Zend_Locale('de_AT');
    $number = Zend_Locale_Format::getNumber('13.524,678',
                                            array('locale' => $locale,
                                                  'precision' => 3)
                                           );

    print $number; // wird 13524.678 zurückgeben

### Genauigkeit und Berechnungen

Da `getNumber($value, array $options = array())` extrem lange Nummern lokalisieren kann, sollte das Ergebnis sorgfältig geprüft werden bevor endlich genaue Berechnungen wie normale mathematische PHP Operationen gemacht werden. Zum Beispiel `if ((string)int_val($number) != $number) { benutze BCMath oder GMP`. Die meisten PHP Installationen unterstützen die BCMath Erweiterung.

Auch die Genauigkeit des dezimalen Ergebnisses kann zu einer gewünschten Länge abgerundet werden bei `getNumber()` mit der Option `'precision'`. Wenn keine Genauigkeit angegeben wurde, wird nicht abgerundet. Für die Angabe der Genauigkeit dürfen nur PHP Integer Zahlen verwendet werden. Das Ergebnis wird nicht gerundet. Deswegen wird "1.6" auch "1" und nicht "2" zurückgeben, wenn als Genauigkeit null angegeben wurde.

Wenn das dezimale Ergebnis zu einer gewünschten Länge abgeschnitten statt gerundet werden soll kann stattdessen die Option `'number_format'` verwendet werden. Die Länge des gewünschten dezimalen Ergebnisses kann mit der gewünschten Länge von Nullen bestimmt werden. Das Ergebnis wird dann nicht gerundet. Wenn also die definierte Genauigkeit innerhalb von `number_format` Null ist wird "1.6" den Wert "1" und nicht "2" zurückgeben. Siehe das folgende Beispiel:

#### Normalisierung von Nummern mit Genauigkeit

    $locale = new Zend_Locale('de_AT');
    $number = Zend_Locale_Format::getNumber('13.524,678',
                                            array('precision' => 1,
                                                  'locale' => $locale)
                                           );
    print $number; // will 13524.7 zurückgeben

    $number = Zend_Locale_Format::getNumber('13.524,678',
                                            array('number_format' => '#.00',
                                                  'locale' => $locale)
                                           );
    print $number; // will 13524.67 zurückgeben

## Lokalisieren von Nummern

`toNumber($value, array $options = array())` kann, mit Hilfe der folgenden unterstützten Gebietsschemata, Nummern lokalisieren. Diese Funktion gibt eine lokalisierte Zeichenkette der angegebenen Nummer in dem konventionellen Format für ein definiertes Gebietsschema aus. Die Option 'number_format' definiert ein explizit angegebenes nicht standardmäßiges Nummernformat für die Verwendung mit `toNumber()`.

### Lokalisieren von Nummern

    $locale = new Zend_Locale('de_AT');
    $number = Zend_Locale_Format::toNumber(13547.36,
                                           array('locale' => $locale));

    // gibt 13.547,36 zurück
    print $number;

### Unlimitierte Länge

`toNumber()` kann Nummern mit unendlicher Länge lokalisieren. Hierbei gibt es keine Abhängigkeiten mit Integer oder Float Limits.

Auf dem selben Web wie unter `getNumber()` verwendet `toNumber()` die Genauigkeit. Wenn keine Genauigkeit angegeben wurde, wird die komplette lokalisierte Nummer zurückgegeben.

### Nummern mit bestimmter Genauigkeit lokalisieren

    $locale = new Zend_Locale('de_AT');
    $number = Zend_Locale_Format::toNumber(13547.3678,
                                           array('precision' => 2,
                                                 'locale' => $locale));

    // gibt 13.547,37 zurück
    print $number;

Wird die Option 'number_format' benutzt, kann ein selbst definiertes Format für das erstellen der Nummer definiert werden. Das Format selbst muß im CLDR Format wie anbei beschrieben angegeben werden. Das Gebietsschema wird hierbei benutzt um das Trennzeichen, die Genauigkeit und andere Formatierungszeichen für Zahlen zu erhalten. Deutsch definiert zum Beispiel ',' als Kommazeichen und im Englischen wird das '.' Zeichen benutzt.

### Definitionen für selbst erzeugte Zahlenformate

Definition | Beschreibung | Beispiel Format | Erzeugte Ausgabe
--- | --- | --- | ---
#0 | Erzeugt eine Zahl ohne Genauigkeit und ohne Trennung | #0 | 1234567
, | Erzeugt eine Trennung mit der Länge von einem Trennzeichen zum nächsten oder zur 0 | #,##0 | 1,234,567
#,##,##0 | Erzeugt eine Standard Trennung von 3 und alle weiteren Trennungen mit 2 | #,##,##0 | 12,34,567
. | Erzeugt eine Kommazahl | #0.# | 1234567.1234
0 | Erzeugt eine Kommazahl mit definierter Länge | #0.00 | 1234567.12

### Ein selbst definiertes Zahlenformat verwenden

    $locale = new Zend_Locale('de_AT');
    $number = Zend_Locale_Format::toNumber(13547.3678,
                                           array('number_format' => '#,#0.00',
                                                 'locale' => 'de')
                                          );

    // gibt 1.35.47,36 zurück
    print $number;

    $number = Zend_Locale_Format::toNumber(13547.3,
                                           array('number_format' => '#,##0.00',
                                                 'locale' => 'de')
                                          );

    // gibt 13.547,30 zurück
    print $number;

## Testen von Zahlen

`isNumber($value, array $options = array())` prüft ob eine gegebene Zeichenkette eine Zahl enthält und gibt `TRUE` oder `FALSE` zurück.

### Testen von Zahlen

    $locale = new Zend_Locale();
    if (Zend_Locale_Format::isNumber('13.445,36', array('locale' => 'de_AT')) {
        print "Zahl";
    } else {
        print "keine Zahl";
    }

## Gleitkommazahlen normalisieren

Lokalisierte Gleitkommazahlen können mit `getFloat($value, array $options = array())` analysiert werden. Es wird eine Gleitkommazahl zurückgegeben.

### Gleitkommazahlen normalisieren

    $locale = new Zend_Locale('de_AT');
    $number = Zend_Locale_Format::getFloat('13.524,678',
                                           array('precision' => 2,
                                                 'locale' => $locale));

    // gibt 13524.68 zurück
    print $number;

## Lokalisieren von Gleitkommazahlen

`toFloat()` kann Gleitkommazahlen lokalisieren. Diese Funktion gibt eine lokalisierte Zeichenkette mit der gegebenen Zahl zurück.

### Lokalisieren von Gleitkommazahlen

    $locale = new Zend_Locale('de_AT');
    $number = Zend_Locale_Format::toFloat(13547.3655,
                                          array('precision' => 1,
                                                'locale' => $locale));

    // gibt 13.547,4 zurück
    print $number;

## Testen von Gleitkommazahlen

`isFloat($value, array $options = array())` prüft ob eine gegebene Zeichenkette eine Gleitkommazahl enthält und gibt `TRUE` oder `FALSE` zurück.

### Testen von Gleitkommazahlen

    $locale = new Zend_Locale('de_AT');
    if (Zend_Locale_Format::isFloat('13.445,36', array('locale' => $locale)) {
        print "Gleitkommazahl";
    } else {
        print "keine Gleitkommazahl";
    }

## Integer Zahlen normalisieren

Integer Zahlen können mit der Funktion `getInteger()` analysiert werden. Es wird ein Integer Wert zurückgegeben.

### Normalisieren von Integer Zahlen

    $locale = new Zend_Locale('de_AT');
    $number = Zend_Locale_Format::getInteger('13.524,678',
                                             array('locale' => $locale));

    // gibt 13524 zurück
    print $number;

## Lokalisieren von Integer Zahlen

`toInteger($value, array $options = array())` kann Integer Zahlen lokalisieren. Diese Funktion gibt eine lokalisierte Zeichenkette anhand der gegebenen Nummer zurück.

### Lokalisieren von Integer Zahlen

    $locale = new Zend_Locale('de_AT');
    $number = Zend_Locale_Format::toInteger(13547.3655,
                                            array('locale' => $locale));

    // gibt 13.547 zurück
    print $number;

## Testen von Integer Zahlen

`isInteger($value, array $options = array())` prüft ob eine gegebene Zeichenkette eine Integer Zahl enthält und gibt `TRUE` oder `FALSE` zurück.

### Testen von Integer Zahlen

    $locale = new Zend_Locale('de_AT');
    if (Zend_Locale_Format::isInteger('13.445', array('locale' => $locale)) {
        print "Integerzahl";
    } else {
        print "keine Integerzahl";
    }

## Konvertieren von Zahlensystemen

`Zend_Locale_Format::convertNumerals()` kann die Ziffern zwischen den unterschiedlichen Zahlensystemen umwandeln. Das inkludiert auch das Standard Arabisch/Europäisch/Lateinische Zahlensystem (0,1,2,3,4,5,6,7,8,9). Nicht zu verwechseln mit dem Ost-arabischen Zahlensystem welches in der Arabischen Sprache benutzt wird um Zahlen zu schreiben. Der Versuch ein nicht unterstütztes Zahlensystem zu benutzen führt zu einer Ausnahme um eine irrtümliche falsche Konvertierung wegen eines Schreibfehlers zu verhindern. Alle Zeichen der Eingabe, welche keine Ziffern des angegebenen Zahlenformates sind, werden in den Ausgabestring kopiert ohne das Sie verändert werden. Das beinhaltet auch die Trennzeichen der Zahlen. `Zend_Locale`* Komponenten sind abhängig von den Daten welche durch die CLDR liefert (hier ist eine Liste von Schreibweisen gruppiert nach Sprachen).

Im CLDR und auch hier, werden die Europäisch/Lateinischen Zahlen als "Latin" bezeichnet und mit dem zugeordneten 4-Zeichen-Code "Latn" referriert. Im CLDR werden Zahlensysteme auch als "Schreibweisen" (Scripts) bezeichnet.

Nehmen wir an eine Web Form erhält eine nummerische Eingabe welche Ost-Arabische Ziffern enthält "١‎٠٠". Die meisten Programme und PHP Funktionen erwarten Eingaben aber als Lateinische Ziffern. Glücklicherweise wird für die Konvertierung dieser Eingabe in gleichwertige Lateinische Ziffern "100" sehr wenig Aufwand. Es muß nur `convertNumerals($inputNumeralString, $sourceNumeralSystem, $destNumeralSystem)` benutzt werden werden welches `$input` zurückgibt und hierbei die Ziffern der Schreibweise `$sourceNumeralSystem` in die Schreibweise `$destNumeralSystem` konvertiert.

### Konvertieren von Ost-Arabischen Ziffern in Europäisch Lateinische Ziffern

    $arabicScript = "١‎٠٠";   // Arabisch für "100" (ein Hundert)
    $latinScript = Zend_Locale_Format::convertNumerals($arabicScript,
                                                       'Arab',
                                                       'Latn');

    print "\nOriginal:   " . $arabicScript;
    print "\nNormalisiert: " . $latinScript;

Genauso kann jedes unterstützte Zahlensystem in jedes andere unterstützte Zahlensystem konvertiert werden.

### Konvertieren von Lateinischen Ziffern in Ost-Arabische Ziffern

    $latinScript = '123';
    $arabicScript = Zend_Locale_Format::convertNumerals($latinScript,
                                                        'Latn',
                                                        'Arab');

    print "\nOriginal:  " . $latinScript;
    print "\nLokalisiert: " . $arabicScript;

### Auslesen des 4 Zeichen CLDR Codes durch Benutzen des Namens in der Muttersprache

    function getScriptCode($scriptName, $locale)
    {
        $scripts2names = Zend_Locale_Data::getList($locale, 'scriptlist');
        $names2scripts = array_flip($scripts2names);
        return $names2scripts[$scriptName];
    }
    echo getScriptCode('Latin', 'en'); // Ausgabe "Latn"
    echo getScriptCode('Tamil', 'en'); // Ausgabe "Taml"
    echo getScriptCode('tamoul', 'fr'); // Ausgabe "Taml"

Für eine Liste der unterstützten Zahlensysteme kann man `Zend_Locale::getTranslationList('numberingsystem', 'en')` aufrufen.