Я не из тех парней, которые говорят, что фреймворк должен быть вашим первым выбором дизайна в каждом веб-приложении, но я хотел бы указать, какие компоненты Zend Framework делают мою жизнь проще. После статьи Zend_Validate, опубликованной на прошлой неделе, настала очередь Zend_Locale.
Internazionalization и локализации (i18n / l10n для друзей) из веб — приложения являются опасения , что не учитывают только перевод слов и фраз на других языках, но идти дальше , чтобы охватить различные форматы пользовательского ввода и вывода , используемых во всем мире. Фактически, большинство веб-приложений генерируют выходные данные из какого-либо источника данных — базы данных или внешних служб — и должны отображать их в соответствии с текущей локалью пользователя . Локаль — это компьютерный термин, который описывает определенную комбинацию языка и региона , которую можно интерпретировать, чтобы выбрать формат для отображения данных или для анализа.
Постановка задачи
Как мы уже ожидали во введении, существует много общих проблем локализации, выходящих за рамки простого перевода веб-страниц:
- отображение или разбор даты в формате «Бог знает что». В Италии мы называем дату публикации этой статьи 12.09.2010 , а для базы данных — 2010-12-09 , а для американца — 9 декабря 2010 года . Обработка даты и времени — это то, что мы видели много раз почти на каждом веб-сайте или в любом приложении.
- отображение суммы денег с правильными разделителями . Вы можете столкнуться с трудностями в том, чтобы воспринимать вас всерьез, если вы допустили ошибку в ваших собственных локализованных ценах: например, Paypal обрабатывает счета в нескольких валютах одновременно.
- отображение простого списка регионов, доступных для локализации , без необходимости извлечения списка из другого тега <select> веб-сайта. И как английское слово пишется на кантонском?
Готовое решение
Zend_Locale является одним из крупнейших компонентов ZF, по крайней мере, в размере файла: он весит несколько мегабайт из-за содержащихся в нем метаданных локали. Большая часть этого не состоит из кода PHP: его папка содержит много файлов XML с информацией о различных языках и регионах мира.
Выбор правильного перевода для данных вашего приложения находится в описании работы Zend_Translate; Zend_Locale является зависимостью от Zend_Translate и содержит много общих переводов часто используемых слов (например, Да и Нет ).
Особенности Zend_Locale, например:
- такие символы, как €, $ … индексируются стандартным ключевым словом в каждой локали, поэтому после настройки текущей страны пользователя вы можете просто напечатать $ array [‘currency’].
- служебные методы для работы с различными представлениями пользователей, для данных, которые в вашей доменной модели и постоянном уровне вашего приложения объединены. Примером могут быть даты, которые в полях базы данных всегда 2010-12-01, но в пользовательских интерфейсах могут быть 12/1/2010 или 1/12/2010, в зависимости от страны.
Вы будете удивлены тем, сколько утилит в Zend_Locale: его размер подтверждается метаданными, которые он передает в приложение PHP бесплатно.
Совет: вы можете удалить файлы XML для локалей, которые вы не собираетесь использовать , освобождая произвольное количество мегабайт, которое вам не придется переносить на ваш сервер при обновлении платформы. Когда-то во времена FTP это была распространенная проблема, и удаление ненужных файлов приводило к уменьшению компонента до сотен килобайт.
пример
Пример кода вызывает Api объекта Zend_Locale и использует некоторые другие классы, ориентированные на локали. Понимание локали означает, что объект Zend_Locale может быть передан (или зарегистрирован глобально, хотя это было бы опасным примером глобального состояния) для изменения поведения.
<?php
ini_set('include_path', ini_get('include_path') . PATH_SEPARATOR . '/home/giorgio/code/zftrunk/library');
require_once 'Zend/Loader/Autoloader.php';
Zend_Loader_Autoloader::getInstance();
class ZendLocaleTest extends PHPUnit_Framework_TestCase
{
private $italianLocale;
public function setUp()
{
// sometimes new Zend_Locale(Zend_Locale::BROWSER) for
// http-headers based recognition
$this->italianLocale = new Zend_Locale('it_IT');
}
public function testParsesALocalizedDateEnteredByAnItalianUser()
{
// or 31/12/2010, which is a standard way to represent a date in Europe
$date = new Zend_Date('31/dic/2010', null, $this->italianLocale);
$this->assertEquals('2010-12-31', $date->toString('Y-M-d'));
}
public function testKnowsTheNameOfLanguageCodesInYourLocale()
{
$list = Zend_Locale::getTranslationList('language', 'it_IT');
// the italian word for 'English'
$this->assertEquals('inglese', $list['en']);
$list = Zend_Locale::getTranslationList('language', 'en_US');
// the English word for 'italiano'
$this->assertEquals('Italian', $list['it']);
}
public function testKnowsWhatSymbolItalianUsesForFloatNumbers()
{
$list = Zend_Locale::getTranslationList('Symbols', 'it_IT');
$this->assertEquals(',', $list['decimal']);
}
public function testKnowsHowSpanishSayMonths()
{
$february = Zend_Locale::getTranslation(2, 'Month', 'es');
$this->assertEquals('febrero', $february);
}
public function testKnowsHowToAnswerQuestions()
{
$questionInfo = $this->italianLocale->getQuestion();
// We say Sì to mean Yes...
$this->assertEquals('sì', $questionInfo['yes']);
// ...while No is simply No
$this->assertEquals('no', $questionInfo['no']);
$this->assertContains('s', $questionInfo['yesarray']);
$this->assertContains('sì', $questionInfo['yesarray']);
// without accent on the i
$this->assertContains('si', $questionInfo['yesarray']);
}
public function testParsesNumbersFromYourLocale()
{
// Who wants to be a millionaire?
$userInput = '1.000.000,00';
// wrong conversion
$this->assertSame(1, (int) $userInput);
$number = Zend_Locale_Format::getNumber($userInput, array(
'locale' => $this->italianLocale,
'precision' => 2
));
$this->assertSame('1000000.00', $number);
// you can safely convert to integer now if you want
$this->assertSame(1000000, (int) $number);
}
public function testFormatsNumbersAccordingToYourLocale()
{
$output = Zend_Locale_Format::toNumber('1000000', array(
'locale' => $this->italianLocale
));
$this->assertEquals('1.000.000', $output);
}
}