diff options
-rw-r--r-- | .gitattributes | 2 | ||||
-rw-r--r-- | demos/quickstart/protected/pages/Advanced/I18N.page | 224 | ||||
-rw-r--r-- | framework/I18N/TTranslateParameter.php | 4 | ||||
-rw-r--r-- | framework/Web/Javascripts/extra/getElementsBySelector.js | 4 | ||||
-rw-r--r-- | tests/FunctionalTests/protected/pages/I18N/BasicI18N.page | 2 | ||||
-rw-r--r-- | tools/texbuilder/build.php | 37 | ||||
-rw-r--r-- | tools/texbuilder/prado3_quick_start.pdf | bin | 335038 -> 475503 bytes | |||
-rw-r--r-- | tools/texbuilder/prado3_quick_start.tex | 38 |
8 files changed, 290 insertions, 21 deletions
diff --git a/.gitattributes b/.gitattributes index 24b0f7c7..f6db162f 100644 --- a/.gitattributes +++ b/.gitattributes @@ -927,5 +927,5 @@ tools/jsbuilder/packer.js -text tools/phpbuilder/build.php -text tools/phpbuilder/files.txt -text tools/texbuilder/build.php -text -tools/texbuilder/prado3_quick_start.pdf -text svneol=unset#unset +tools/texbuilder/prado3_quick_start.pdf -text tools/texbuilder/prado3_quick_start.tex -text diff --git a/demos/quickstart/protected/pages/Advanced/I18N.page b/demos/quickstart/protected/pages/Advanced/I18N.page index e8b5282e..1bb5a9a0 100644 --- a/demos/quickstart/protected/pages/Advanced/I18N.page +++ b/demos/quickstart/protected/pages/Advanced/I18N.page @@ -1,6 +1,228 @@ <com:TContent ID="body" >
<h1>Internationalization (I18N) and Localization (L10N)</h1>
-TBC
+<p>Many web application built with PHP will not have internationalization in mind when it was first written. It may be that it was not intended for use in languages and cultures. Internationalization is an important aspect due to the increase adoption of the Internet in many non-English speaking countries. The process of internationalization and localization will contain difficulties. Below are some general guidelines to internationalize an existing application.</p>
+
+<h2>Separate culture/locale sensitive data</h2>
+
+<p>Identify and separate data that varies with culture. The most obvious are text/string/message. Other type of data should also be considered. The following list categorize some examples of culture sensitive data
+</p>
+
+<ul>
+ <li> Strings, Messages, Text, in relatively small units (e.g. phrases, sentences, paragraphs, but not the full text of a book).</li>
+ <li> Labels on buttons.</li>
+ <li> Help files, large units of text, static text.</li>
+ <li> Sounds.</li>
+ <li> Colors.</li>
+ <li> Graphics,Icons.</li>
+ <li> Dates, Times.</li>
+ <li> Numbers, Currency, Measurements.</li>
+ <li> Phone numbers.</li>
+ <li> Honorifics and personal titles.</li>
+ <li> Postal address.</li>
+ <li> Page layout.</li>
+</ul>
+
+<p>If possible all manner of text should be isolated and store in a persistence format. These text include, application error messages, hard coded strings in PHP files, emails, static HTML text, and text on form elements (e.g. buttons).</p>
+
+<h2>Configuration</h2>
+<p>To enable the localization features in Prado, you need to add a few configuration options in your <a href="?page=Configurations.AppConfig">application configuration</a>.
+First you need to include the <tt>System.I18N.*</tt> namespace to your paths.
+</p>
+<com:TTextHighlighter Language="xml" CssClass="source">
+<paths>
+ <using namespace="System.I18N.*" />
+</paths>
+</com:TTextHighlighter>
+
+<p>Then, if you wish to translate some text in your application, you need to add one translation message data source.</p>
+<com:TTextHighlighter Language="xml" CssClass="source">
+<module id="globalization" class="TGlobalization">
+ <translation type="XLIFF"
+ source="MyApp.messages"
+ autosave="true" cache="true" />
+</module>
+</com:TTextHighlighter>
+
+<p>Where <tt>source</tt> in <tt>translation</tt> is the dot path to a directory
+where you are going to store your translate message catalogue. The <tt>autosave</tt>
+attribute if enabled, saves untranslated messages back into the message catalogue.
+With <tt>cache</tt> enabled, translated messages are saved in the application <tt>runtime/i18n</tt> directory.
+</p>
+
+<p>With the configuration complete, we can now start to localize your application. If you have <tt>autosave</tt> enabled, after running your application with some localization activity (i.e. translating some text), you will see a directory and a <tt>messages.xml</tt> created within your <tt>source</tt> directory.</p>
+
+<h2>What to do with <tt>messages.xml</tt>?</h2>
+<p>The translation message catalogue file, if using <tt>type="XLIFF"</tt>, is a standardized translation message interchange XML format. You can edit the XML file using any UTF-8 aware editor. The format of the XML is something like the following.</p>
+
+<com:TTextHighlighter Language="xml" CssClass="source">
+<?xml version="1.0"?>
+<xliff version="1.0">
+ <file original="I18N Example IndexPage"
+ source-language="EN"
+ datatype="plaintext"
+ date="2005-01-24T11:07:53Z">
+ <body>
+
+<trans-unit id="1">
+<source>Hello world.</source>
+<target>Hi World!!!</target>
+</trans-unit>
+
+ </body>
+ </file>
+</xliff>
+</com:TTextHighlighter>
+
+Each translation message is wrapped within a <tt>trans-unit</tt> tag, where <tt>source</tt> is the original message, and <tt>target</tt> is the translated message. Editors such as <a href="http://www.heartsome.net/EN/xlfedit.html">Heartsome XLIFF Translation Editor</a> can help in editing these XML files.
+
+
+<h2>Setting and Changing Culture</h2>
+<p>Once globalization is enabled, you can access the globalization settings, such as, <tt>Culture</tt>, <tt>Charset</tt>, etc, using </p>
+<com:TTextHighlighter CssClass="source">
+$globalization = $this->getApplication()->getGlobalization();
+echo $globalization->Culture;
+$globalization->Charset= "GB-2312"; //change the charset
+</com:TTextHighlighter>
+
+<p>You also change the way the culture is determined by changing the <tt>class</tt> attribute in the module configuration. For example, to set the culture that depends on the browser settings, you can use the <tt>TGlobalizationAutoDetect</tt> class.
+<com:TTextHighlighter Language="xml" CssClass="source">
+<module id="globalization" class="TGlobalizationAutoDetect">
+ ...
+</module>
+</com:TTextHighlighter>
+
+<p>You may also provide your own globalization class to change how the application culture is set.
+Lastly, you can change the globalization settings on page by page basis using <a href="?page=Configurations.Templates1#tct">template control tags</a>. For example, changing the <tt>Culture</tt> to "zh".</p>
+<com:TTextHighlighter Language="prado" CssClass="source">
+<%@ Application.Globalization.Culture="zh" %>
+</com:TTextHighlighter>
+
+<h2>Localizing your Prado application</h2>
+There are two areas in your application that may need message or string localization, in PHP code and in the templates. To localize strings within PHP, use the <tt>localize</tt> function detailed below. To localize text in the template, use the <a href="#ttranslate">TTranslate</a> component.
+<h2>Using <tt>localize</tt> function to translate text within PHP</h2>
+
+<p>The <tt>localize</tt> function searches for a translated string that matches original from your translation source. First, you need to locate all the hard coded text in PHP that are displayed or sent to the end user. The following example localizes the text of the <tt>$sender</tt> (assuming, say, the sender is a button). The original code before localization is as follows.
+<com:TTextHighlighter CssClass="source">
+function clickMe($sender,$param)
+{
+ $sender->Text="Hello, world!";
+}
+</com:TTextHighlighter>
+
+<p>The hard coded message "Hello, world!" is to be localized using the <tt>localize</tt> function. </p>
+<com:TTextHighlighter CssClass="source">
+function clickMe($sender,$param)
+{
+ $sender->Text=localize("Hello, world!");
+}
+</com:TTextHighlighter>
+
+<h2>Compound Messages</h2>
+
+<p>Compound messages can contain variable data. For example, in the message "There are 12 users online.", the integer 12 may change depending on some data in your application. This is difficult to translate because the position of the variable data may be difference for different languages. In addition, different languages have their own rules for plurals (if any) and/or quantifiers. The following example can not be easily translated, because the sentence structure is fixed by hard coding the variable data within message.</p>
+<com:TTextHighlighter CssClass="source">
+$num_users = 12;
+$message = "There are " . $num_users . " users online.";
+</com:TTextHighlighter>
+
+This problem can be solved using the <tt>localize</tt> function with string substitution. For example, the <tt>$message</tt> string above can be constructed as follows.
+<com:TTextHighlighter CssClass="source">
+$num_users = 12;
+$message = localize("There are {num_users} users online.", array('num_users'=>$num_users));
+</com:TTextHighlighter>
+<p>Where the second parameter in <tt>localize</tt> takes an associative array with the key as the substitution to find in the text and replaced it with the associated value.
+The <tt>localize</tt> function does not solve the problem of localizing languages that have plural forms, the solution is to use <a href="#choice-format">TChoiceFormat</a>.</p>
+
+<h1>I18N Components</h1>
+<a name="ttranslate"></a>
+<h2>TTranslate</h2>
+<p>Messages and strings can be localized in PHP or in templates.
+To translate a message or string in the template, use <tt>TTranslate</tt>.</p>
+
+<com:TTextHighlighter Language="prado" CssClass="source">
+<com:TTranslate>Hello World</com:TTranslate>
+<com:TTranslate Text="Goodbye" />
+</com:TTextHighlighter>
+
+<p><tt>TTranslate</tt> can also perform string substitution. Any attributes of <tt>TTranslate</tt> will be substituted with <tt>{attribute name}</tt> in the translation. E.g.</p>
+<com:TTextHighlighter Language="prado" CssClass="source">
+<com:TTranslate time="late">
+The time is {time}.
+</com:TTranslate>
+</com:TTextHighlighter>
+
+<p>A short for <tt>TTranslate</tt> is also provided using the following syntax.</p>
+<com:TTextHighlighter Language="prado" CssClass="source">
+<%[string]>
+</com:TTextHighlighter>
+<p>where string will be translated to different languages according to the end-user's language preference. This syntax can be used with attribute values as well.</p>
+<com:TTextHighlighter Language="prado" CssClass="source">
+<com:TLabel Text="<%[ Hello World! ]%>" />
+</com:TTextHighlighter>
+
+<h2>TDateFormat</h2>
+<p>Formatting localized date and time is straight forward.</p>
+<com:TTextHighlighter Language="prado" CssClass="source">
+<com:TDateFormat Value="12/01/2005" />
+</com:TTextHighlighter>
+
+<p>There are of 4 localized date patterns and 4 localized time patterns. They can be used in any combination. If using a combined pattern, the first must be the date, followed by a space, and lastly the time pattern. For example, full date pattern with short time pattern.</p>
+
+<com:TTextHighlighter Language="prado" CssClass="source">
+<com:TDateFormat Pattern="fulldate shorttime" />
+</com:TTextHighlighter>
+
+<p>If the <tt>Value</tt> property is not specified, the current date and time is used.</p>
+
+<h2>TNumberFormat</h2>
+<p>PRADO's Internationalization framework provide localized currency formatting and number formatting. Please note that the <tt>TNumberFormat</tt> component provides formatting only, it does not perform current conversion or exchange.</p>
+
+<com:TTextHighlighter Language="prado" CssClass="source">
+<com:TNumberFormat Type="currency" Value="100" />
+</com:TTextHighlighter>
+
+<p><tt>Culture</tt> and <tt>Currency</tt> properties may be specified to format locale specific numbers. </p>
+
+
+<h2>TTranslateParameter</h2>
+<p>Compound messages, i.e., string substitution, can be accomplished with <tt>TTranslateParameter</tt>.
+In the following example, the strings "{greeting}" and "{name}" will be replace
+with the values of "Hello" and "World", respectively.The substitution string must be enclose with "{" and "}". The parameters can be further translated by using <tt>TTranslate</tt>.
+
+<com:TTextHighlighter Language="prado" CssClass="source">
+<com:TTranslate>
+ {greeting} {name}!
+ <com:TTranslateParameter Key="name">World</com:TTranslateParameter>
+ <com:TTranslateParameter Key="greeting">Hello</com:TTranslateParameter>
+</com:TTranslate>
+</com:TTextHighlighter>
+
+
+<a name="choice-format"></a>
+<h2>TChoiceFormat</h2>
+
+<p>Using the <tt>localize</tt> function or <tt>TTranslate</tt> component to translate messages does not inform the translator the cardinality of the data required to determine the correct plural structure to use. It only informs them that there is a variable data, the data could be anything. Thus, the translator will be unable to determine with respect to the substitution data the correct plural, language structure or phrase to use . E.g. in English, to translate the sentence, "There are {number} of apples.", the resulting translation should be different depending on the <tt>number</tt> of apples.</p>
+
+<p>The <tt>TChoiceFormat</tt> component performs message/string choice translation. The following example demonstrated a simple 2 choice message translation.</p>
+
+<com:TTextHighlighter Language="prado" CssClass="source">
+<com:TChoiceFormat Value="1"/>[1] One Apple. |[2] Two Apples</com:TChoiceFormat>
+</com:TTextHighlighter>
+
+<p>In the above example, the <tt>Value</tt> "1" (one), thus the translated string
+is "One Apple". If the <tt>Value</tt> was "2", then it will show "Two Apples".</p>
+
+<p>The message/string choices are separated by the pipe "|" followed by a set notation of the form.</p>
+<ul>
+ <li><tt>[1,2]</tt> -- accepts values between 1 and 2, inclusive.</li>
+ <li><tt>(1,2)</tt> -- accepts values between 1 and 2, excluding 1 and 2.</li>
+ <li><tt>{1,2,3,4}</tt> -- only values defined in the set are accepted.</li>
+ <li><tt>[-Inf,0)</tt> -- accepts value greater or equal to negative infinity
+ and strictly less than 0</li>
+</ul>
+
+<p>Any non-empty combinations of the delimiters of square and round brackets are acceptable.
+The string chosen for display depends on the <tt>Value</tt> property. The <tt>Value</tt> is evaluated for each set until the <tt>Value</tt> is found to belong to a particular set.</p>
</com:TContent>
\ No newline at end of file diff --git a/framework/I18N/TTranslateParameter.php b/framework/I18N/TTranslateParameter.php index f162d642..d00e33bb 100644 --- a/framework/I18N/TTranslateParameter.php +++ b/framework/I18N/TTranslateParameter.php @@ -28,8 +28,8 @@ * <code>
* <com:TTranslate>
* {greeting} {name}!
- * <com:TTranslateParameter Key="name">World</com:TParam>
- * <com:TTranslateParameter Key="greeting">Hello</com:TParam>
+ * <com:TTranslateParameter Key="name">World</com:TTranslateParameter>
+ * <com:TTranslateParameter Key="greeting">Hello</com:TTranslateParameter>
* </com:TTranslate>
* </code>
*
diff --git a/framework/Web/Javascripts/extra/getElementsBySelector.js b/framework/Web/Javascripts/extra/getElementsBySelector.js index d6675cd5..592872fc 100644 --- a/framework/Web/Javascripts/extra/getElementsBySelector.js +++ b/framework/Web/Javascripts/extra/getElementsBySelector.js @@ -30,13 +30,13 @@ function getAllChildren(e) { matching the CSS selector. Selectors can contain element names,
class names and ids and can be nested. For example:
- <pre><tt>elements = document.getElementsBySelect('div#main p a.external')</tt></pre>
+ <pre><tt>elements = $CSS('div#main p a.external')</tt></pre>
Will return an array of all 'a' elements with 'external' in their
class attribute that are contained inside 'p' elements that are
contained inside the 'div' element which has id="main"
*/
-document.getElementsBySelector = function(selector) {
+$CSS = function(selector) {
// Attempt to fail gracefully in lesser browsers
if (!document.getElementsByTagName) {
return new Array();
diff --git a/tests/FunctionalTests/protected/pages/I18N/BasicI18N.page b/tests/FunctionalTests/protected/pages/I18N/BasicI18N.page index d4725015..24cb9831 100644 --- a/tests/FunctionalTests/protected/pages/I18N/BasicI18N.page +++ b/tests/FunctionalTests/protected/pages/I18N/BasicI18N.page @@ -1,4 +1,4 @@ -<%@ Title="Basic I18N Test" %>
+<%@ Title="Basic I18N Test" Culture="zh_CN" %>
<com:TContent ID="Content">
<h1>Basic I18N Test</h1>
<com:TTranslate>
diff --git a/tools/texbuilder/build.php b/tools/texbuilder/build.php index 0cea6aee..1866f868 100644 --- a/tools/texbuilder/build.php +++ b/tools/texbuilder/build.php @@ -35,6 +35,16 @@ $pages['Controls'] = array( 'Controls/DataList.page',
'Controls/DataGrid.page');
+$pages['Advanced Topics'] = array(
+ 'Advanced/Assets.page',
+ 'Advanced/MasterContent.page',
+ 'Advanced/Themes.page',
+ 'Advanced/State.page',
+ 'Advanced/Logging.page',
+ 'Advanced/I18N.page',
+ 'Advanced/Error.page',
+ 'Advanced/Performance.page');
+
//-------------- END CONFIG ------------------
@@ -47,7 +57,9 @@ function escape_verbatim($matches) function include_image($matches)
{
global $current_path;
- $image = dirname($current_path).'/'.$matches[1];
+
+ $image = dirname($current_path).'/'.trim($matches[1]);
+
$file = realpath($image);
$info = getimagesize($file);
switch($info[2])
@@ -128,10 +140,8 @@ function parse_html($page,$html) $html = preg_replace('/<\/?com:TContent[^>]*>/', '', $html);
$html = preg_replace('/<\/?p>/m', '', $html);
- //headings
- $html = preg_replace('/<h1[^>]*>([^<]+)<\/h1>/', '\section{$1}', $html);
- $html = preg_replace('/<h2[^>]*>([^<]+)<\/h2>/', '\subsection{$1}', $html);
- $html = preg_replace('/<h3[^>]*>([^<]+)<\/h3>/', '\subsubsection{$1}', $html);
+ //escape { and }
+ $html = preg_replace('/([^\s]+){([^}]*)}([^\s]+)/', '$1\\\{$2\\\}$3', $html);
//codes
$html = str_replace('$', '\$', $html);
@@ -140,18 +150,16 @@ function parse_html($page,$html) $html = preg_replace_callback('/(`1`)([^`]*)(`2`)/m', 'escape_verbatim', $html);
$html = preg_replace_callback('/(<div class="source">)([^<]*)(<\/div>)/', 'escape_verbatim', $html);
-
- $html = preg_replace_callback('/<img\s+src="<%~([^"]*)%>"[^\\/]*\/>/', 'include_image', $html);
+ $html = preg_replace_callback('/<img\s+src="?<%~([^"]*)%>"?[^\\/]*\/>/', 'include_image', $html);
//runbar
$html = preg_replace('/<com:RunBar\s+PagePath="([^"]*)"\s+\/>/',
'Try, \texttt{http://../quickstart/index.php?page=$1}', $html);
-
//text modifiers
- $html = preg_replace('/<b>([^>]*)<\/b>/', '\textbf{$1}', $html);
- $html = preg_replace('/<i>([^>]*)<\/i>/', '\emph{$1}', $html);
- $html = preg_replace('/<tt>([^>]*)<\/tt>/', '\texttt{$1}', $html);
+ $html = preg_replace('/<b>([^<]*)<\/b>/', '\textbf{$1}', $html);
+ $html = preg_replace('/<i>([^<]*)<\/i>/', '\emph{$1}', $html);
+ $html = preg_replace('/<tt>([^<]*)<\/tt>/', '\texttt{$1}', $html);
//links
$html = preg_replace_callback('/<a[^>]+href="([^"]*)"[^>]*>([^<]*)<\/a>/',
@@ -167,6 +175,13 @@ function parse_html($page,$html) $html = preg_replace('/<li>/', '\item ', $html);
$html = preg_replace('/<\/li>/', '', $html);
+ //headings
+ $html = preg_replace('/<h1>([^<]+)<\/h1>/', '\section{$1}', $html);
+ $html = preg_replace('/<h2>([^<]+)<\/h2>/', '\subsection{$1}', $html);
+ $html = preg_replace('/<h3>([^<]+)<\/h3>/', '\subsubsection{$1}', $html);
+
+
+
$html = html_entity_decode($html);
diff --git a/tools/texbuilder/prado3_quick_start.pdf b/tools/texbuilder/prado3_quick_start.pdf Binary files differindex 4f6ddbf1..39aa440c 100644 --- a/tools/texbuilder/prado3_quick_start.pdf +++ b/tools/texbuilder/prado3_quick_start.pdf diff --git a/tools/texbuilder/prado3_quick_start.tex b/tools/texbuilder/prado3_quick_start.tex index 675ec357..737804c5 100644 --- a/tools/texbuilder/prado3_quick_start.tex +++ b/tools/texbuilder/prado3_quick_start.tex @@ -59,12 +59,45 @@ \pagenumbering{roman}
\tableofcontents
-\newpage
-
\chapter*{Preface}
\addcontentsline{toc}{chapter}{Preface}
Prado quick start doc
+\chapter*{License}
+\addcontentsline{toc}{chapter}{License}
+PRADO is free software released under the terms of the following BSD license.\\
+Copyright 2004-2006, PradoSoft (http://www.pradosoft.com)\\
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+\begin{enumerate}
+ \item Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+
+ \item Redistributions in binary form must reproduce the above copyright notice,
+this list of conditions and the following disclaimer in the documentation
+and/or other materials provided with the distribution.
+
+\item Neither the name of the developer nor the names of its contributors may
+be used to endorse or promote products derived from this software without
+specific prior written permission.
+\end{enumerate}
+
+\begin{verbatim}
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+\end{verbatim}
+
+
\newpage
\pagestyle{fancyplain}
@@ -79,5 +112,4 @@ Prado quick start doc \include{ch7}
\include{ch8}
-
\end{document}
|