Как добавить интернациональную поддержку в ваши PHP-приложения

Ознакомьтесь с инструментами и стратегиями, которые помогут сделать PHP-приложения готовыми к использованию каждым

Локализацию приложения можно планировать, а можно реализовывать впопыхах и задним числом. Ознакомьтесь с такими методиками и инструментами как gettext, XML, XSLT и конструктивные шаблоны, которые могут помочь при встраивании локализации в готовый продукт, или при планировании локализации заранее.

Роберт Брэдли, консультант, Свободный писатель

Обладая более чем 20-летним опытом в области проектирования ПО, Роберт Брэдли (Robert Bradley) работает неполный день и занимается писательской деятельностью и консалтингом. Он применял свой полузабытый немецкий в примерах переводов.



24.05.2007

Оценка приложения

Требования к локализации могут быть довольно туманными, например "подготовить это приложение для Германии". Но даже когда кажется, что требования подробны, вы можете обнаружить вещи, которые менеджер по продукту упустил из виду.

Возьмём, к примеру, приложение Yahoo! RSS news reader, показанное в Листинге 1. Когда страница вызывается в первый раз, отображается список заголовков по умолчанию, а также поле формы, в которое можно впечатать выбранную категорию новостей перед повторной отправкой страницы. Приложение проверяет введённую категорию и либо выводит сообщение об ошибке, если категория введена неправильно, либо отображает заголовки запрошенной категории.

Листинг 1. RSS news от Yahoo!
<?php

require_once "XML/RSS.php";

# Нормализация и проверка пользовательского ввода

$newstype = strtolower(isset($_POST['newstype']) ? $_POST['newstype'] : "tech");
$error = null;
switch($newstype) {
  case 'world':
  case 'tech':
	break;
  default:
	$error = 'Invalid news type.';
	break;
}

?>

<html>
<head>
<title>RSS Feed from Yahoo News</title>
</head>
<body>
<h1>RSS Feed from Yahoo News</h1>

<p>
Добро пожаловать в Yahoo RSS news reader. Для просмотра заголовков различных новостей
введите тип новости в поле внизу, а затем отправьте форму. Допустимые типы новостей - 
'tech' и 'world'.
</p>
<p>
<form method = "POST">

<?php
  if (isset($error)) {
	echo '<br/><font color = "red">' . $error . '</font><br/>';
  }
?>

<input type = "text" name = "newstype" value = "<?php echo $newstype ?>" />
<br>
<input type = "submit">
</form>
</p>
  
<?php
  $url = "http://rss.news.yahoo.com/rss/" . $newstype;
  $rss = new XML_RSS($url);
  $rss->parse();
  echo "<ul>\n";
  foreach ($rss->getItems() as $item) {
	echo "<li><a href=\" . $item['link'] . "\">" . $item['title'] . "</a></li>\n";
  }
  echo "</ul>\n";
?>
  
</body>
</html>

Даже в таком простом виде, это приложение иллюстрирует многие проблемы, возникающие в ходе локализации. Оно также отражает некоторые преимущества и недостатки любого скриптового языка.

Всегда можно сделать продукт быстро, но за это придётся заплатить свою цену. Пользовательский интерфейс (UI), бизнес-логика и конфигурация, или же их отсутствие, смешиваются вместе, безо всякой мысли о поддержке или расширении страницы новыми функциям.

При локализации этой страницы для немецкого, и, возможно, других языков, становятся очевидными несколько препятствий:

  • Следует провести рефакторинг кода для выделения различных уровней приложения.
  • Текст пользовательского интерфейса, например, заголовки, содержание и сообщения об ошибках, нужно извлечь и перевести.
  • Элементы управления формами, например, кнопку Submit (отправить), нужно локализовать.
  • В приложении должен быть предусмотрен способ определения целевой локали (target locale).
  • Требования к пользовательскому вводу и его проверка изменяются в зависимости от локали.
  • Рассмотрите бизнес-правила, зависящие от места действия, например, URL для RSS-каналов Yahoo!; места назначения и синтаксис меняются от страны к стране.
  • Увеличивается потребность в среде, поддерживающей настройку и управление поведением области приложения для каждой локали.

Усилия, затраченные на всё это, могут быть такими же, как при создании собственно приложения, или превосходить их - горькая пилюля для всех, кого это касается. В итоге ваша команда должна быть готова взять этот барьер - до или после завершения работы над приложением.


Терминология по локализации

Если в ходе проекта вам придётся иметь дело с переводчиками, хорошо бы убедиться, что вы понимаете некоторые термины, которые вы, вероятно, встретите, общаясь с ними. В Таблице 1 даны определения нескольких общеупотребительных терминов, используемых лингвистами и специалистами по переводу.

Таблица 1. Терминология по локализации
ТерминЗначение
ЛокальКомбинация языка и страны/региона - например, en_US, en_GB, de_DE
Интернационализация (I18N)Планирование, проектирование и подготовка приложений к локализации
Локализация (L10N)Определение и перевод (T9N) пользовательского интерфейса приложения для целевой локали
Экстернализация (извлечение строк)Процесс извлечения строк программы для перевода

Встраивание локализации

Листинг 2 показывает, как выглядит приложение RSS после рефакторинга и модернизации для поддержки локализации. Функциональная логика и среда локализации абстрагируются в класс обработчика (handler class). Всё, что остаётся в основном коде - это конструирование объекта обработчика страниц, шаблон HTML и обращения к методам accessor обработчика для наполнения динамических фрагментов шаблона HTML.

Листинг 2. Локализация RSS news
<?php
# news2.php
require_once "RSSHandler.php";
$handler = new RSSHandler;
?>

<html>
  <head>
    <meta content="text/html; charset=utf-8" http-equiv="Content-Type">
    <title><?php echo $handler->getTitle() ?></title>
  </head>
  <body>
    <h1><?php echo $handler->getTitle() ?></h1>
    <p>
      <?php echo $handler->getGreeting() ?>
    </p>
    <?php $handler->showerror() ?>
    <form method = "POST">
      <input type = "text" name = "newstype" 
        value = "<?php echo $handler->getNewstype() ?>" />
      <br/>
      <input type = "submit" 
        value="<?php echo $handler->getSubmitbutton() ?>" />
    </form>
    <?php $handler->showHeadlines() ?>
  </body>
</html>

Преимущество рефакторинга состоит в том, что, возможно, программистам легче осуществлять поддержку кода. При этом вызывает сомнение, что пользовательский интерфейс стало легче поддерживать при отсутствии лингвистического контекста и встраивании значительных фрагментов HTML в PHP-код.

Доверят ли PHP-программисты выполнять подобные изменения Web-разработчику? Какую цену придётся платить за то, что разработчикам внутреннего интерфейса приходится иметь дело с второстепенными запросами на изменение в пользовательском интерфейсе? Позднее я покажу вам, каким образом язык Extensible Stylesheet Language Transformation (XSLT) может помочь в разграничении уровней приложения.

Конструктор

Начнём с конструктора для класса обработчика (см. Листинг 3), чтобы увидеть, каким образом страница была изменена для локализации. При создании экземпляра обработчика страницы конструктор определяет соответствующую локаль, извлекает параметры конфигурации для этой локали, проверяет ввод пользователя, вычисляет весь некогда статический контент, руководствуясь текущей локалью пользователя, а затем проверяет любой пользовательский ввод. (Исходный код см. в разделе Downloads.)

Листинг 3. RSSHandler.php
  public function __construct() {

    # настройка локали
    putenv("LANG=de_DE");       # для конфигурации
    setlocale(LC_ALL, 'de_DE');   # для gettext

    # Получение зависящей от локали конфигурации
    $this->conf = new RSSConfig;
    $this->configdecorator = new Configdecorator($this->conf);

    # установка окружения извлечения текста
    bindtextdomain($this->conf->getTextdomainmessage(),  
      $this->conf->getTextdomainpath());
    textdomain($this->conf->getTextdomainmessage());
    
    # Извлечение текста для перевода.
    $errormsg = gettext("News type is not valid.");
    $this->title = gettext("Yahoo RSS News");
    $this->submitbutton = gettext("Get the news.");
    $lgreeting = 
      gettext("Welcome to the Yahoo RSS news reader. ") . " " .
      gettext("Enter a news type, then submit the form.") . " " .
      gettext ("Valid news types are: %s.");
    $decoratedtypes = $this->configdecorator->getNewsTypes();
    $this->greeting = sprintf($lgreeting, $decoratedtypes);
    
    # Нормализация и проверка 
    $this->newstype = $this->normalize();
    $this->error = $this->validate() ? ' : $errormsg;
  }

В данном примере ради простоты локаль жёстко закодирована на de_DE. В реальной жизни вам потребуется настраивать локаль в зависимости от бизнес-требований. Два общепринятых способа определения правильной локали - посмотреть URL запроса (например, www.ebay.de, amazon.fr), или же просто спросить пользователя и установить в его браузере cookie-файл с предпочтениями.

Извлечение параметров конфигурации

После определения локали обработчик извлекает параметры конфигурации для Германии. В данном примере конфигурация предполагает использование пакета PEAR (Config.php), конфигурационный XML-файл (RSSConfig.xml), надстройку, относящуюся к области приложения (RSSConfig.php) и простой класс decorator для добавления HTML-разметки для некоторых параметров конфигурации (Configdecorator.php).

Конфигурационный файл, показанный в Листинге 4, хранит информацию в XML-формате. Он определяет окружение извлечения строки (//conf/textdomain) - местонахождение зависимых от локали компонентов и имя файла сообщений.

Примечание: Если вы загрузили и пробовали запустить примеры, обязательно измените путь к извлечённым и переведённым строкам, чтобы он соответствовал вашей среде.

Конфигурационные файлы также сообщают приложению, как сконструировать правильный URL новостного канала Yahoo! (//conf/de_DE/baseurl), как проверить выбор пользователем типа новостного канала (//conf/de_DE/newtypes) и какой тип новостей должен использоваться по умолчанию, если пользователь не сделал выбора.

Листинг 4. Configuration.xml
<?xml version="1.0" encoding="UTF-8"?>
<conf>
    <textdomain>
    	<path>/home/bbradley/Sites</path>
	<messagefile>messages</messagefile>
    </textdomain>
    <en_US>
        <baseurl>http://rss.news.yahoo.com/rss/</baseurl>
        <newstypes>
            <type>
                <default>true</default>
                <name>tech</name>
                <url>tech</url>
                </type>
            <type>
                <default/>
                <name>world</name>
                <url>world</url>
                </type>
        </newstypes>
    </en_US>
    <de_DE>
        <baseurl>http://de.news.yahoo.com/</baseurl>
        <newstypes>
            <type>
                <default>true</default>
                <name>Ausland</name>
                <url>politik/ausland.html.xml</url>
                </type>
            <type>
                <name>Technik</name>
                <url>technik/index.html.xml</url>
                </type>
        </newstypes>
    </de_DE>
</conf>

Конфигурацию можно сделать более устойчивой к сбоям, добавив локаль "по умолчанию". В этом случае, если приложение пытается выполнить недопустимую локаль, всегда можно гарантировать какое-то разумное поведение приложения. Также можно расширить конфигурацию для задействования других возможностей приложения, например кобрендинга или ограничений на основе прав пользователей.

Остальная часть объекта обработчика отвечает в основном за порождение текстовых фрагментов страницы соответствующим образом для каждой локали и обеспечение публичных методов accessor, которые делают эти кусочки переведённого текста доступными HTML-шаблону.

Среда извлечения gettext

Приложение использует среду извлечения строк с открытым исходным кодом под названием gettext для фактуализации переведённых строк. Эта среда имеет несколько преимуществ:

  • Она бесплатная.
  • Она работает на множестве платформ.
  • Она работает со многими языками программирования, в том числе и с PHP.
  • Она особенно подходит для модернизации (retrofitting).

Чтобы использовать gettext:

  1. Создайте структуру каталогов для всех локалей, поддержку которых необходимо обеспечить.
  2. Разметьте строки, передвигая их в аргументы специальной функции gettext().
  3. Запустите утилиту командной строки xgettext для извлечения строк в файл сообщений.
  4. Скопируйте получившийся файл сообщений в каждую директорию для локали.
  5. Отредактируйте локальные версии файла сообщений и переведите текст.
  6. Запустите утилиту командной строки msgfmt для создания локализованных баз данных сообщений, которые будут использоваться во время выполнения.

Важно понимать, что функция gettext() служит очевидной цели извлечения локализованного текста во время выполнения. Но также важно и то, что она является ещё и маркером для извлечения текста. Утилита xgettext ищет строки, которые отмечает эта функция.

Все программные компоненты примера приложения, в том числе структура каталогов, определённая в конфигурации приложения, приведены в Листинге 5. Для каждой реализации gettext требуется аналогичная структура каталогов. Не требуется создавать дерево каталогов или базу данных сообщений для локали по умолчанию; строки для этой локали уже внедрены в код. Однако вам потребуется отредактировать файл RSSConfig.xml, точно указав полный путь к этим файлам для среды gettext.

Листинг 5. Структура каталогов
ConfigDecorator.php - класс Decorator
de_DE - директория для Германии
	LC_MESSAGES - поддиректория для сообщений
		messages.mo - база данных скомпилированных сообщений
		messages.po - переведённые сообщения
messages.po - создаётся xgettext
news2.php - главное приложение / HTML-шаблон
RSSConfig.php - класс конфигурации приложения
RSSConfig.xml - конфигурационный файл приложения
RSSHandler.php - обработчик HTTP-запросов / бизнес-логика

Перевод файла сообщений

В немецком файле сообщений жирным шрифтом отмечены те части, которые должен предоставить переводчик. Другими словами, переводчик должен заполнить пустые поля. Когда переводчик в первый раз открывает файл сообщений, эти части будут пустыми, а переводчик должен указать кодировку, которую он или она будет использовать, в данном случае, Latin-1, а также сделать переводы. ID сообщения (msgid) - это оригинальный текст, отмеченный для извлечения с помощью вызова функции gettext(). Строка сообщения (msgstr) - это та строка, которая должна быть в языке, на который делается перевод. В Листинге 6 показан перевод сообщения об ошибке, которое выдаётся, когда пользователь указывает неправильный тип новостей.

Листинг 6. Немецкий файл сообщений, messages.po.de
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid "
msgstr "
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2006-11-05 11:05-0800\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=ISO-8859-1\n"
"Content-Transfer-Encoding: 8bit\n"

#: RSSHandler.php:31
msgid "News type is not valid."
msgstr "Die Nachrichtkategorie ist falsch."

При каком-либо изменении текста любой извлечённой строки, во время следующего создания файла сообщений будет создаваться и новое ID сообщения. Всякий раз, когда добавляются или изменяются строки, файл сообщений следует генерировать заново, иначе в целевых локалях новый текст будет отображаться непереведённым.

В производственной среде все эти задачи (помимо подготовки исходного кода) обычно выполняет группа L10N. Но это не означает, что вы можете совершенно не уделять внимание лингвистическим проблемам. При локализации предложения не забывайте о следующих моментах:

  • Не внедряйте в строки функциональную информацию.
  • Используйте маркеры printf для динамического содержимого в целом предложении, вместо того, чтобы разрывать предложение на несколько строк. Помните, что порядок слов в предложении в различных языках разный; не нужно лишать переводчика возможности менять порядок слов. Если строка содержит более одного динамического элемента, msgfmt поддерживает расширенный синтаксис разметки, позволяющий указывать положение каждого динамического элемента в строке. При переводе порядок элементов легко изменить. Более подробно о позиционном синтаксисе можно узнать из любого онлайнового руководства по gettext (см. Ресурсы).
  • Убедитесь, что по контексту строки можно однозначно понять её значение. Имейте в виду, что переводчики видят только строки, а не работающее приложение.

Примечание: для получения более подробной информации по лингвистическим аспектам локализации ПО см. Ресурсы.

При добавлении нового текста или изменении существующего, группа по локализации может применять другие утилиты gettext для слияния новых или изменённых строк с существующими файлами сообщений, что снимает необходимость повторного перевода.


Проектирование локализации

Описанный выше подход к локализации вполне пригоден во многих случаях. Но с увеличением масштаба, имеет смысл подумать о проектировании приложений с помощью конструктивных шаблонов. Один из наиболее широко используемых шаблонов - Модель-Представление-Контроллер (MVC). Этот шаблон предлагает рассматривать приложение как совокупность различных уровней - презентации, управляющей логики и доступа к данным. Ещё одно преимущество MVC состоит в том, что с его помощью легче расширять контроллер и представление для обработки других типов HTTP-запросов либо как SOAP-сервисов, либо как XML API.

Шаблон RSS MVC

Struts, Ruby on Rails и Zend Framework основаны на такой многоуровневой философии проектирования. Если вы находите подход MVC привлекательным, изучите Zend Framework for PHP. Однако, чтобы уменьшить количество дополнительных пакетов, необходимых для примера приложения, я использую свой собственный MVC-шаблон, показанный в Листинге 7.

Размер основного кода стал теперь ещё меньше. Он работает как контроллер, занимаясь по большей части обслуживанием HTTP-запросов. Он конструирует объект домена, задействующий бизнес-правила, которые мы уже обсуждали, извлекает модель данных сессии из домена, а затем передаёт модель классу представления для её трансформации в HTML, который отправляется обратно клиенту.

Листинг 7. Контроллер RSS news, news3.php
<?php
# news3.php
require_once "View.php"; 
require_once "RSSDomain.php";

putenv("LANG=de_DE");
$domain = new RSSDomain;
$model = $domain->getModel();
$view = new View($domain->getTemplate(), $model);
echo $view->asHTML();
?>

Та же используемая ранее схема конфигурации приложения по-прежнему управляет поведением бизнес-правил. Изменился способ обработки пользовательского интерфейса нового уровня презентации. Этот уровень больше не использует поддержку HTML-шаблонов PHP. Вместо этого он полагается на XSL-трансформации. Модель домена - это рекурсивная структура данных вложенных объектов, которые можно реализовать как XML. Представление заставляет шаблон XSL трансформировать XML-представление данных сессии в локализованный HTML, возвращаемый браузеру клиента.

Уровень презентации

XML-модель и XSL-шаблон, формирующие ядро уровня презентации показаны в Листинге 8. Модель содержит информацию о конфигурации, например типы новостей, в особенности то, как они могут отображаться для пользователя (//rss/newstypes/displaytypes). Модель также возвращает выбор пользователем типа новостей (//rss/userinput/newstype), а также доставленные заголовки новостей и URL (//rss/headlinelist/headline). Если пользовательский выбор типа новостей был недопустимым, вместо заголовков модель возвратит код ошибки. Шаблон XSL получает доступ к фрагментам возвращённой модели данных для конструирования HTML, который отображается в браузере клиента.

Листинг 8. Образец модели XML и шаблона XSL (RSSView.xsl)
 <rss>
 	<newstypes>
		<displaytypes>Ausland, Technik</displaytypes>
		<typelist>
			<type>Technik</type>
			<type>Ausland</type>
		</typelist>
	</newstypes>
	<userinput>
		<newstype>Ausland</newstype>
	</userinput>
	<headlinelist>
		<headline>
		<hlink>http://de.news.yahoo.com/01112006/12/guatemala.html</hlink>
		<htitle>Guatemala und Venezuela halten Besprechungen</htitle>
		</headline>
		<headline>
		<hlink>http://de.news.yahoo.com/01112006/12/mandat.html</hlink>
		<htitle>Mandat einer Regierung in Afrika</htitle>
		</headline>
	</headlinelist>
</rss> 

---------------------------------------------------------------

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:variable name="pagetitle">Yahoo Schlagzeilen</xsl:variable>
<xsl:variable name="submitbutton">Hol Schlagzeilen</xsl:variable>
<xsl:variable name="displaytypes">
<xsl:value-of select="/rss/newstypes/displaytypes"/>
</xsl:variable>
<xsl:variable name="newstype">
<xsl:value-of select="/rss/userinput/newstype"/>
</xsl:variable>

<xsl:template match="/">
<html>
	<head>
		<meta content="text/html; charset=utf-8" http-equiv="Content-Type"/>
		<title>
			<xsl:value-of select="$pagetitle"/>
		</title>
	</head>
	<body>
		<h1><xsl:value-of select="$pagetitle"/></h1>
		<p>
		Willkommen! Um den Yahoo Nachrichtleser zu gebrauchen, gib einen von den 
		folgenden Nachrichttypen ein:  \
		<xsl:value-of select="/rss/newstypes/displaytypes"/>!
		</p>
		<!-- errors  -->
		<xsl:choose>
			<xsl:when test="rss/userinput/error/code">
				<p><b><font color="red">Falscher Typ</font></b></p>
			</xsl:when>
		</xsl:choose>
		<p>
		<form method = "POST">
			<input type = "text" name = "newstype" value = "{$newstype}" />
			<br/>
			<input type = "submit" value="{$submitbutton}" />
		</form>
		</p>
		<!-- headlines  -->
		<xsl:for-each select="/rss/headlinelist/headline">
			<a><xsl:attribute name="href">
			<xsl:value-of select="hlink"/>
			</xsl:attribute><xsl:value-of select="htitle"/></a>
			<br/>
		</xsl:for-each>
	</body>
</html>
</xsl:template>
</xsl:stylesheet>

При таком подходе локализованные строки не извлекаются инструментом типа gettext. Вместо этого, каждая локаль имеет собственный XSL-шаблон. Поскольку теперь имеется понятный языковой контекст, распределять рабочую нагрузку при поддержке приложения должно быть легче. Web-разработчики, группа по локализации и даже менеджеры по продуктам могут взять на себя ответственность за реализацию самых незначительных связанных с пользовательским интерфейсом исправлений ошибок и запросов на создание функции.

Для конструирования HTML класс представления использует поддержку XSL, идущую с PHP V5, модель данных и шаблон XSL. PHP V4 делает это по-другому. Данный подход также демонстрируется для тех ситуаций, когда необходимо локализовать старое приложение. В большинстве случаев XSLT включено по умолчанию, однако может потребоваться включить обработку XSLT в вашей установке PHP, чтобы всё это заработало. В Листинге 9 показана XSL-трансформация.

Листинг 9. XSL-трансформация (View.php)
	public function asHTML() {
		$xml = new DomDocument;
		$modelxml = $this->model->asXML();
		#system('echo " ' . $modelxml . ' " > /tmp/l.txt');
		$xml->loadXML($modelxml);
		$xsl = new DomDocument;
		$xsl->load($this->template);
		$proc = new xsltprocessor;
		$proc->importStyleSheet($xsl);
		$html = $proc->transformToXML($xml);
		
#      Following is XSL transformation syntax for PHP4
#		$xh = xslt_create();
#		$arguments = array ('/_xml' => \
$this->model->asXML(),  '/_xsl' => $this->template);
#		$html = xslt_process($xh, 'arg:/_xml', $this->template, 
#                                          NULL, $arguments, $this->parameters);
#		xslt_free($xh);

		return $html;
	}

Если в проекте задействованы более крупные команды, всё равно имеет смысл извлекать строки и генерировать XSL-шаблоны из главного шаблона. Это обычно выполняется при помощи системы управления глобализацией (globalization management system - GMS). Затем Web-разработчики имеют дело только с XSL-шаблонами по умолчанию на предпочитаемом на предприятии языке, а переводчики используют функции системы управления, и, возможно, системы машинного перевода типа SYSTRAN.

После окончания разработки, когда приходит время выпускать продукт, типичный процесс локализации может выглядеть следующим образом:

  • GMS извлекает весь текст из основных XSL-шаблонов и обновляет базу данных переводов.
  • Группа L10N использует базу данных переводов для перевода новых строк и повторного перевода изменившихся строк.
  • GMS реконструирует локализованные XSL-шаблоны для каждой локали из базы данных переводов.

Хотя использование GMS и несёт очевидные выгоды, вероятно, не следует применять её при работе в небольшой группе или со зрелым приложением, которое не так уж сильно изменяется. При работе со всеми упомянутыми инструментами следует взвесить как выгоды, так и затраты на получение, реализацию и поддержку того из них, который вы решили использовать.


Заключение

В такой короткой статье невозможно рассмотреть все трудности, с которыми вы можете столкнуться. Например, я не затрагивал работу с кодировками, датами, валютами и числами вообще, а также адресами и телефонными номерами. В большинстве случаев нужно в правильном формате вывести даты и валюты для локали. Также следует понимать, как проверять и интерпретировать суммы в валюте и даты, когда пользователи из разных стран впечатывают их в форму.

Тем не менее, представленные приёмы позволят вам выполнять 80 процентов того, что необходимо сделать для локализации приложения. Если вы работаете с уже существующим приложением и имеются временные и бюджетные ограничения, сконцентрируйтесь на менее амбициозном подходе - модернизации. Если же вы разрабатываете новое приложение или имеете достаточные ресурсы для локализации существующего, не бойтесь быть более агрессивными, если это окупится. В результате вы получите не только безупречно локализованный продукт, но и значительно облегчите работу людям, которые будут осуществлять поддержку приложения, что бы им не пришлось делать - исправлять ошибку или добавлять новую функцию.


Загрузка

ОписаниеИмяРазмер
Примеры скриптов1os-php-intl.zip12KB

Заметка

  1. Файл .tar содержит полный исходный код, за исключением следующих необходимых модулей PEAR: XML_RSS и Config. Также следует убедиться, что в вашей установке PHP включена поддержка XSLT.

Ресурсы

Научиться

  • Оригинал статьи: How to internationalize your PHP apps.
  • В Википедии (Wikipedia) имеется хорошая вводная информация по локализации ПО и GMS'ам.
  • GNU - хорошая отправная точка для знакомства с установкой и использованием gettext.
  • Статья developerWorks "Что за язык XSLT?" Майкла Кея (Michael Kay) - хорошая отправная точка для знакомства с XSLT.
  • SYSTRAN - одна из наиболее известных систем машинного перевода на рынке.
  • Прочитайте "Пять стандартных конструктивных шаблонов PHP", чтобы ознакомиться с более подробной информацией по использованию конструктивных шаблонов с PHP.
  • "Понимание среды Zend" - ещё одна хорошая статья о MVC и PHP.
  • Посетите проектные ресурсы PHP IBM developerWorks, чтобы узнать больше о PHP.
  • Семинары и обучение на IBM developerWorks Россия.
  • Узнайте о запланированных конференциях, демонстрациях, web-трансляциях и других событиях во всём мире, представляющих интерес для разработчиков ПО IBM с открытым исходным кодом.
  • Посетите раздел ПО с открытым исходным кодом developerWorks, чтобы получить обширную справочную информацию, инструменты и обновления проектов, которые помогут вам выполнять разработку с помощью технологий с открытым исходным кодом и использовать их с продуктами IBM.
  • Чтобы послушать интересные интервью и дискуссии для разработчиков ПО, обязательно посетите подкасты developerWorks.

Получить продукты и технологии

  • Внесите новшество в ваш следующий проект разработки с открытым исходным кодом с помощью пробного ПО IBM, доступного для загрузки или на DVD.

Обсудить

Комментарии

developerWorks: Войти

Обязательные поля отмечены звездочкой (*).


Нужен IBM ID?
Забыли Ваш IBM ID?


Забыли Ваш пароль?
Изменить пароль

Нажимая Отправить, Вы принимаете Условия использования developerWorks.

 


Профиль создается, когда вы первый раз заходите в developerWorks. Информация в вашем профиле (имя, страна / регион, название компании) отображается для всех пользователей и будет сопровождать любой опубликованный вами контент пока вы специально не укажите скрыть название вашей компании. Вы можете обновить ваш IBM аккаунт в любое время.

Вся введенная информация защищена.

Выберите имя, которое будет отображаться на экране



При первом входе в developerWorks для Вас будет создан профиль и Вам нужно будет выбрать Отображаемое имя. Оно будет выводиться рядом с контентом, опубликованным Вами в developerWorks.

Отображаемое имя должно иметь длину от 3 символов до 31 символа. Ваше Имя в системе должно быть уникальным. В качестве имени по соображениям приватности нельзя использовать контактный e-mail.

Обязательные поля отмечены звездочкой (*).

(Отображаемое имя должно иметь длину от 3 символов до 31 символа.)

Нажимая Отправить, Вы принимаете Условия использования developerWorks.

 


Вся введенная информация защищена.


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=40
Zone=Open source
ArticleID=226112
ArticleTitle=Как добавить интернациональную поддержку в ваши PHP-приложения
publish-date=05242007