Home > po polsku, technicznie > Lokalizowanie dat z Zend Framework

Lokalizowanie dat z Zend Framework

November 6th, 2008 MiB Leave a comment Go to comments

Wczoraj na Planecie PHP znalazłem wpis Locale-Sensitive Dates in PHP. Autorka opisuje zagadnienie obsługi dat, w kontekście ich tłumaczenia na różne języki. Proponowanym rozwiązaniem jest skorzystanie z kombinacji funkcji setlocale oraz strftime. Nie jest to jednak rozwiązanie idealne, gdyż wymaga, aby środowisko, w którym działa aplikacja, obsługiwało wybrany zestaw znaków. W dyskusji zaproponowałem rozwiązanie oparte o Zend Framework, które chciałbym pokrótce przedstawić.

Do obsługi dat wykorzystamy Zend_Date, zaś ich lokalizację powierzymy Zend_Locale.

Przygotowanie środowiska

Nim przystąpimy do zabawy datami należy przygotować środowisko. W tym celu ze strony projektu pobieramy najnowszą wersję frameworka (w chwili pisania artykułu mamy do dyspozycji stabilną wersję 1.6.2 oraz niestabilną 1.7.0) i rozpakowujemy. Następnie tworzymy plik date.php i przygotowujemy ZF do działania:

< ?php
header( 'Content-type: text/html; charset=utf-8' );
// ścieżka
define( 'DS', DIRECTORY_SEPARATOR );
define(' APPLICATION_PATH', realpath( dirname( __FILE__ ) ) );
set_include_path( APPLICATION_PATH . DS . '3rd_party' . DS .
                         PATH_SEPARATOR . get_include_path() );
// autoload
require_once "Zend/Loader.php";
Zend_Loader::registerAutoload();
// ustawiam strefę czasową- wymagane przez Zend_Date!
date_default_timezone_set( 'Europe/Warsaw' );
?>

Najważniejsza jest linia 6, w której definiujemy katalog, gdzie ZF powinien szukać swoich klas. Tak przygotowani możemy rozpocząć walkę z lokalizowaniem dat!

Zend_Locale

ZF posiada rozbudowaną obsługę l10n i i18n. która oprócz obsługi tłumaczeń pozwala na prostą obsługę walut, formatów zapisu liczb, jednostek miary oraz – co najbardziej nas interesuje – daty. Framework dystrybuowany jest z dość rozbudowaną biblioteką tłumaczeń, obsługującą nazwy dni, miesięcy, najczęściej spotykane formaty dat itp. Dzięki temu używanie Zend_Locale staje się banalnie proste i sprowadza się do 1 linijki:

< ?php $locale = new Zend_Locale( 'pl_PL' ); ?>

Twórcy ZF poszli jednak dalej, pozwalając w prosty sposób dostosowywać się do języka używanego przez użytkownika, pobierając tą informację z jego przeglądarki. Przykładowy kod, wraz z obsługą wyjątku, gdy wybrany język nie jest obsługiwany przez ZF, jest równie trywialny jak poprzedni przykład:

< ?php
try {
    $locale = new Zend_Locale( Zend_Locale::BROWSER );
} catch( Zend_Locale_Exception $e ) {
    $locale = new Zend_Locale( 'pl_PL' );
}
?>

Warto wspomnieć jeszcze o możliwości wykorzystania Zend_Cache, aby przyspieszyć działanie aplikacji (lokalizacje trzymane są w pliku XML).

Zend_Date

Zend_Date pozwala w prosty sposób operować datami- parsować, prezentować w różnych formatach, dodawać i odejmować. Co ważne- operacje nie są ograniczone do zakresu unix epoch! Przykładowe wykrozystanie Zend_Date:

< ?php
echo new Zend_Date(); // wyświetli aktualną datę w predefiniowanym formacie
 
echo new Zend_Date( '2008-11-03 8:34:40' ); // wyświetli podaną datę w predefiniowanym formacie
?>

A jak do tego wszystkiego ma się Zend_Locale? Sprzężenie obu modułów jest zadaniem trywialnie prostym:

< ?php
// polska lokalizacja
echo new Zend_Date( new Zend_Locale( 'pl_PL' ) ); // wyświetli aktualną datę w formacie Y-m-d H:i:s
?>

Predefiniowana data zależna jest od wybranej lokalizacji, co ma znaczenie choćby w kwestii podawania godzin (format 12 lub 24 godzinny). Poniżej zamieszczam kilka przykładów użycia Zend_Date wraz z Zend_Locale. Dodam tylko, że domyślnie Zend_Date przyjmuje wyświetla daty w formacie zgodnym z ISO, to zachowanie można jednak zmienić, co uczyniłem w niniejszym przykładzie:

< ?php
// format daty będę podawał zgodnie z formatem PHP, a nie ISO
Zend_Date::setOptions( array( 'format_type' => 'php' ) );
// polska lokalizacja
$locale = new Zend_Locale( 'pl_PL' );
echo new Zend_Date( $locale );
// wyświetli aktualną datę w formacie Y-m-d H:i:s
$date   = new Zend_Date( '2008-11-03 8:34:40', $locale );
echo $date->toString( 'l, j F, Y, H:i' ); // wyświetli: poniedziałek, 3 listopada, 2008, 08:34
// angielska lokalizacja
$locale = new Zend_Locale( 'en_EN' );
echo new Zend_Date( $locale ); // wyświetli aktualną datę w formacie M j, Y g:i:s A
?>

Automatyzacja zadań

Dalej nie pozostaje już nic innego jak tylko rozpropagować informacje o używanej lokalizacji na inne komponenty. Dokumentacja ZF wskazuje Zend_Registry jako najprostszy sposób by tego dokonać:

< ?php
Zend_Registry::set('Zend_Locale',$locale);
?>

Jednak w ostatniej stabilnej wersji ZF (1.6.2) nie doszukałem się odwołania do Zend_Registry wewnątrz Zend_Locale czy Zend_Date, co powoduje, że i tak instancję Zend_Locale należy przesyłać jawnie. Mam nadzieję, że nadchodzące wydanie (1.7) zmieni coś w tej kwestii. Osoby zainteresowane tematem odsyłam do dokumentacji ZF po więcej szczegółów.

  1. August 17th, 2009 at 03:35 | #1

    A jak sprawic, zeby Zend nie wyswietlil nazwy miesiaca w postaci:

    stycznia

    tylko:

    styczeń

    ?? Probuje, probuje i jakos nie bardzo wiem jak.

  1. No trackbacks yet.

Powered by WP Hashcash