<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array"/>
  <modified type="array">
    <modified>
      <diff>@@ -1,17 +1,22 @@
 &lt;?php
-
 require '../../h2o.php';
 
 $template = new H2o('trans.html', array(
     'cache'=&gt; false,
     'i18n' =&gt; array(
         'locale' =&gt; isset($_GET['lang']) ? $_GET['lang'] : false,
+        'charset' =&gt; 'UTF-8',
         'gettext_path' =&gt; '../bin/gettext/bin/',
         'extract_message' =&gt; true,
         'compile_message' =&gt; true,
     )
 ));
 
+# Setup custom gettext resolver
+
+
+$time_start = microtime(true);
+
 echo $template-&gt;render(array(
     'users' =&gt; array(
         array(
@@ -36,5 +41,6 @@ echo $template-&gt;render(array(
         )
     )
 ));
+echo &quot;in &quot;.(microtime(true) - $time_start).&quot; seconds\n&lt;br/&gt;&quot;;
 
 ?&gt;
\ No newline at end of file</diff>
      <filename>example/i18n/index.php</filename>
    </modified>
    <modified>
      <diff>@@ -7,9 +7,9 @@ msgid &quot;&quot;
 msgstr &quot;&quot;
 &quot;Project-Id-Version: template translation\n&quot;
 &quot;Report-Msgid-Bugs-To: \n&quot;
-&quot;POT-Creation-Date: 2008-11-25 13:38+1100\n&quot;
-&quot;PO-Revision-Date: 2008-11-13 02:44+1000\n&quot;
-&quot;Last-Translator: Taylor Luk\n&quot;
+&quot;POT-Creation-Date: 2009-02-17 16:25+1100\n&quot;
+&quot;PO-Revision-Date: 2009-02-17 16:18+1000\n&quot;
+&quot;Last-Translator: Taylor luk &lt;subjective@gmail.com&gt;\n&quot;
 &quot;Language-Team: \n&quot;
 &quot;MIME-Version: 1.0\n&quot;
 &quot;Content-Type: text/plain; charset=UTF-8\n&quot;
@@ -29,24 +29,18 @@ msgid &quot;Finish&quot;
 msgstr &quot;Fertig stellen&quot;
 
 msgid &quot;&quot;
-&quot;  \n&quot;
 &quot;    (software engineering) The act or process of making a product suitable &quot;
 &quot;for \n&quot;
 &quot;    international markets, typically by making text messages easily &quot;
 &quot;translatable \n&quot;
 &quot;    and ensuring support of non-Latin character sets.\n&quot;
-&quot;    \n&quot;
-&quot;\t&quot;
 msgstr &quot;&quot;
-&quot;  \n&quot;
 &quot;     (Software Engineering) Die Handlung oder Verfahren zur Herstellung &quot;
 &quot;eines Produktes geeignet f&#252;r \n&quot;
 &quot;     internationalen M&#228;rkten, die in der Regel durch das Erstellen von Text-&quot;
 &quot;Nachrichten leicht zu vermitteln \n&quot;
 &quot;     und die Gew&#228;hrleistung von Unterst&#252;tzung von nicht-lateinischen &quot;
 &quot;Zeichens&#228;tzen. \n&quot;
-&quot;     \n&quot;
-&quot;\t&quot;
 
 msgid &quot;Pluralization support&quot;
 msgstr &quot;Pluralisierung Unterst&#252;tzung&quot;</diff>
      <filename>example/i18n/locale/de/LC_MESSAGES/messages.po</filename>
    </modified>
    <modified>
      <diff>@@ -7,9 +7,9 @@ msgid &quot;&quot;
 msgstr &quot;&quot;
 &quot;Project-Id-Version: template translation\n&quot;
 &quot;Report-Msgid-Bugs-To: \n&quot;
-&quot;POT-Creation-Date: 2008-11-25 13:38+1100\n&quot;
-&quot;PO-Revision-Date: 2008-11-13 03:01+1000\n&quot;
-&quot;Last-Translator: Taylor Luk\n&quot;
+&quot;POT-Creation-Date: 2009-02-17 16:25+1100\n&quot;
+&quot;PO-Revision-Date: 2009-02-17 16:18+1000\n&quot;
+&quot;Last-Translator: Taylor luk &lt;subjective@gmail.com&gt;\n&quot;
 &quot;Language-Team: \n&quot;
 &quot;MIME-Version: 1.0\n&quot;
 &quot;Content-Type: text/plain; charset=UTF-8\n&quot;
@@ -29,22 +29,16 @@ msgid &quot;Finish&quot;
 msgstr &quot;Maali&quot;
 
 msgid &quot;&quot;
-&quot;  \n&quot;
 &quot;    (software engineering) The act or process of making a product suitable &quot;
 &quot;for \n&quot;
 &quot;    international markets, typically by making text messages easily &quot;
 &quot;translatable \n&quot;
 &quot;    and ensuring support of non-Latin character sets.\n&quot;
-&quot;    \n&quot;
-&quot;\t&quot;
 msgstr &quot;&quot;
-&quot;  \n&quot;
 &quot;(Software Engineering) Lakia tai prosessin tehd&#228; tuote soveltuu \n&quot;
 &quot;     kansainv&#228;lisill&#228; markkinoilla, tyypillisesti tekem&#228;ll&#228; tekstiviestej&#228; &quot;
 &quot;helposti k&#228;&#228;nnett&#228;viss&#228; \n&quot;
 &quot;     ja varmistamaan tuki ei-latinalaisia merkist&#246;j&#228;. \n&quot;
-&quot;    \n&quot;
-&quot;\t&quot;
 
 msgid &quot;Pluralization support&quot;
 msgstr &quot;Pluralization tukea&quot;</diff>
      <filename>example/i18n/locale/fi/LC_MESSAGES/messages.po</filename>
    </modified>
    <modified>
      <diff>@@ -7,9 +7,9 @@ msgid &quot;&quot;
 msgstr &quot;&quot;
 &quot;Project-Id-Version: template translation\n&quot;
 &quot;Report-Msgid-Bugs-To: \n&quot;
-&quot;POT-Creation-Date: 2008-11-25 13:38+1100\n&quot;
-&quot;PO-Revision-Date: 2008-11-13 03:07+1000\n&quot;
-&quot;Last-Translator: Taylor Luk\n&quot;
+&quot;POT-Creation-Date: 2009-02-17 16:25+1100\n&quot;
+&quot;PO-Revision-Date: 2009-02-17 16:13+1000\n&quot;
+&quot;Last-Translator: Taylor luk &lt;subjective@gmail.com&gt;\n&quot;
 &quot;Language-Team: \n&quot;
 &quot;MIME-Version: 1.0\n&quot;
 &quot;Content-Type: text/plain; charset=UTF-8\n&quot;
@@ -29,22 +29,18 @@ msgid &quot;Finish&quot;
 msgstr &quot;Terminer&quot;
 
 msgid &quot;&quot;
-&quot;  \n&quot;
 &quot;    (software engineering) The act or process of making a product suitable &quot;
 &quot;for \n&quot;
 &quot;    international markets, typically by making text messages easily &quot;
 &quot;translatable \n&quot;
 &quot;    and ensuring support of non-Latin character sets.\n&quot;
-&quot;    \n&quot;
-&quot;\t&quot;
 msgstr &quot;&quot;
-&quot;  \n&quot;
-&quot;(g&#233;nie logiciel) L'acte ou processus de fabrication d'un produit adapt&#233; &#224; \n&quot;
+&quot;    (g&#233;nie logiciel) L'acte ou processus de fabrication d'un produit adapt&#233; &quot;
+&quot;&#224; \n&quot;
 &quot;     les march&#233;s internationaux, g&#233;n&#233;ralement en faisant des messages texte &quot;
 &quot;facilement traduisible \n&quot;
 &quot;     et d'assurer le soutien de la non-latino-jeux de caract&#232;res. \n&quot;
 &quot;    \n&quot;
-&quot;\t&quot;
 
 msgid &quot;Pluralization support&quot;
 msgstr &quot;Pluralisation de soutien&quot;
@@ -75,6 +71,10 @@ msgstr[1] &quot;&quot;
 &quot;\t\t     %(name) a %(count) t&#226;ches \n&quot;
 &quot;\t\t&quot;
 
+# C:\workspace\h2o\example\i18n\trans.html:7
+#~ msgid &quot;    (software engineering)\n&quot;
+#~ msgstr &quot;    (software engineering fr)\n&quot;
+
 #~ msgid &quot;Insert title here&quot;
 #~ msgstr &quot;Ins&#233;rer le titre ici&quot;
 </diff>
      <filename>example/i18n/locale/fr/LC_MESSAGES/messages.po</filename>
    </modified>
    <modified>
      <diff>@@ -1,67 +1,65 @@
-&lt;!DOCTYPE html PUBLIC &quot;-//W3C//DTD HTML 4.01 Transitional//EN&quot; &quot;http://www.w3.org/TR/html4/loose.dtd&quot;&gt;
-&lt;html&gt;
-&lt;head&gt;
-&lt;meta http-equiv=&quot;Content-Type&quot; content=&quot;text/html; charset=UTF-8&quot;&gt;
-&lt;title&gt;{% trans &quot;Internationalized templates&quot; %}&lt;/title&gt;
-&lt;/head&gt;
-&lt;body&gt;
-
-&lt;div id=&quot;header&quot;&gt;
-	&lt;h1&gt;{{  _(&quot;Internationalized templates&quot;) }}&lt;/h1&gt;
-
-	{% trans &quot;Select languages&quot; %}
-	
-	&lt;a href=&quot;?lang=en&quot;&gt;{% trans &quot;English&quot; %}&lt;/a&gt; |
-	&lt;a href=&quot;?lang=fi&quot;&gt;{% trans &quot;Finish&quot;%} &lt;/a&gt; |
-	&lt;a href=&quot;?lang=fr&quot;&gt;{% trans &quot;French: %}&lt;/a&gt; |
-	&lt;a href=&quot;?lang=de&quot;&gt;{% trans &quot;German: %}&lt;/a&gt;
-
-  &lt;p&gt;
-  {% blocktrans %}
-  
-    (software engineering) The act or process of making a product suitable for 
-    international markets, typically by making text messages easily translatable 
-    and ensuring support of non-Latin character sets.
-    
-	{% endblocktrans %}
-	&lt;/p&gt;
-
-&lt;/div&gt;
-
-
-&lt;div id=&quot;content&quot;&gt;
-  &lt;h2&gt;{% trans &quot;Pluralization support&quot; %}&lt;/h2&gt;
-  
-	{% blocktrans count=users.length %}
-	    there is one {{ count }} item.
-	{% plural %}
-	    there are number of {{ count }} items.
-	{% endblocktrans %}
-	&lt;/p&gt;
-	
-	&lt;ul&gt;
-	{% for index, user in users %}
-	    {{ user.username }} - {{ user.tasks.length }}
-	&lt;li style=&quot;color:{% cycle 'grey', 'pink' %}&quot;&gt;
-	    {{ index }}
-		{% blocktrans count=user.tasks.length, name=user.username|capitalize %}
-		    {{ name }} has {{ count }} task
-		{% plural %}
-		    {{ name }} has {{ count }} tasks
-		{% endblocktrans %}
-	
-		&lt;ol&gt;
-		{% for task in user.tasks %}
-		   &lt;li&gt;{{ task }}&lt;/li&gt;
-		{% endfor %}
-		&lt;/ol&gt;
-	&lt;/li&gt;
-	{% endfor %}
-	&lt;/ul&gt;
-&lt;/div&gt;
-
-&lt;div id=&quot;footer&quot;&gt;
-    
-&lt;/div&gt;
-&lt;/body&gt;
-&lt;/html&gt;
+&lt;!DOCTYPE html PUBLIC &quot;-//W3C//DTD HTML 4.01 Transitional//EN&quot; &quot;http://www.w3.org/TR/html4/loose.dtd&quot;&gt;
+&lt;html&gt;
+&lt;head&gt;
+&lt;meta http-equiv=&quot;Content-Type&quot; content=&quot;text/html; charset=UTF-8&quot;&gt;
+&lt;title&gt;{% trans &quot;Internationalized templates&quot; %}&lt;/title&gt;
+&lt;/head&gt;
+&lt;body&gt;
+
+&lt;div id=&quot;header&quot;&gt;
+	&lt;h1&gt;{{  _(&quot;Internationalized templates&quot;) }}&lt;/h1&gt;
+
+	{% trans &quot;Select languages&quot; %}
+	
+	&lt;a href=&quot;?lang=en&quot;&gt;{% trans &quot;English&quot; %}&lt;/a&gt; |
+	&lt;a href=&quot;?lang=fi&quot;&gt;{% trans &quot;Finish&quot;%} &lt;/a&gt; |
+	&lt;a href=&quot;?lang=fr&quot;&gt;{% trans &quot;French: %}&lt;/a&gt; |
+	&lt;a href=&quot;?lang=de&quot;&gt;{% trans &quot;German: %}&lt;/a&gt;
+
+  &lt;p&gt;
+{% blocktrans %}
+    (software engineering) The act or process of making a product suitable for 
+    international markets, typically by making text messages easily translatable 
+    and ensuring support of non-Latin character sets.
+{% endblocktrans %}
+	&lt;/p&gt;
+
+&lt;/div&gt;
+
+
+&lt;div id=&quot;content&quot;&gt;
+  &lt;h2&gt;{% trans &quot;Pluralization support&quot; %}&lt;/h2&gt;
+    &lt;p&gt;
+	{% blocktrans count=users.length %}
+	    there is one {{ count }} item.
+	{% plural %}
+	    there are number of {{ count }} items.
+	{% endblocktrans %}
+	&lt;/p&gt;
+	
+	&lt;ul&gt;
+	{% for index, user in users %}
+	    {{ user.username }} - {{ user.tasks.length }}
+	&lt;li style=&quot;color:{% cycle 'grey', 'pink' %}&quot;&gt;
+	    {{ index }}
+		{% blocktrans count=user.tasks.length, name=user.username|capitalize %}
+		    {{ name }} has {{ count }} task
+		{% plural %}
+		    {{ name }} has {{ count }} tasks
+		{% endblocktrans %}
+	
+		&lt;ol&gt;
+		{% for task in user.tasks %}
+		   &lt;li&gt;{{ task }}&lt;/li&gt;
+		{% endfor %}
+		&lt;/ol&gt;
+	&lt;/li&gt;
+	{% endfor %}
+	&lt;/ul&gt;
+&lt;/div&gt;
+
+&lt;div id=&quot;footer&quot;&gt;
+    
+&lt;/div&gt;
+&lt;/body&gt;
+&lt;/html&gt;</diff>
      <filename>example/i18n/trans.html</filename>
    </modified>
    <modified>
      <diff>@@ -11,7 +11,8 @@ class Trans_Tag extends H2o_Node {
     
     function render($context, $stream) {
         if ($this-&gt;text) {
-            $stream-&gt;write(gettext($this-&gt;text));
+            $gettext = H2o_I18n::$gettext;
+            $stream-&gt;write(call_user_func($gettext, $this-&gt;text));
         }
     }
 }
@@ -38,6 +39,7 @@ class Blocktrans_Tag extends H2o_Node {
 
         # Parse singular and plural block
         $this-&gt;singular = $parser-&gt;parse('plural', 'endblocktrans');
+        
         if ($parser-&gt;token-&gt;content === 'plural') {
             $this-&gt;plural = $parser-&gt;parse('endblocktrans');
         }
@@ -74,7 +76,12 @@ class Blocktrans_Tag extends H2o_Node {
             $this-&gt;count = count($this-&gt;count);
             
         # Get translation
-        $output = ngettext($this-&gt;singular, $this-&gt;plural, $this-&gt;count);
+        $ngettext = H2o_I18n::$ngettext;
+        $gettext = H2o_I18n::$gettext;
+        if ($this-&gt;plural)
+            $output = call_user_func($ngettext, $this-&gt;singular, $this-&gt;plural, $this-&gt;count);
+        else
+            $output = call_user_func($gettext, $this-&gt;singular);
 
         # Variable in output
         foreach(array_keys($this-&gt;vars) as $var) {
@@ -107,11 +114,14 @@ class Blocktrans_Tag extends H2o_Node {
 
 class H2o_I18n {
     var $locale;
+    var $charset = 'UTF-8';
     var $locale_dir;
     var $tmp_dir;
     var $extensions = array('html','tpl');
     var $gettext_path = '';
     var $gettext_setup = false;
+    static $gettext = 'gettext';
+    static $ngettext = 'ngettext';
     
     function __construct($path, $options = array()) {
         if (is_file($path))
@@ -121,7 +131,6 @@ class H2o_I18n {
         $this-&gt;locale_dir = $this-&gt;searchpath .'locale'.DS;
         $this-&gt;options = $options;
         
-
         if (isset($options['tmp_dir']))
             $this-&gt;tmp_dir = $options['tmp_dir'];
         else
@@ -129,35 +138,34 @@ class H2o_I18n {
         
         if (isset($options['ext']))
             $this-&gt;extensions = $options['ext'];
-
-        if (isset($options['locale']) &amp;&amp; $options['locale']) {
+            
+        if (isset($options['charset']))
+            $this-&gt;charset = $options['charset'];
+            
+        if (isset($options['locale']) &amp;&amp; $options['locale'])
             $this-&gt;setLocale($options['locale']);
-        }
         
-        if (isset($options['extract_message']) &amp;&amp; $options['extract_message']) {
+        if (isset($options['extract_message']) &amp;&amp; $options['extract_message'])
             $this-&gt;extract();
-        }
         
-        if (isset($options['compile_message']) &amp;&amp; $options['compile_message']) {
+        if (isset($options['compile_message']) &amp;&amp; $options['compile_message'])
             $this-&gt;compile();
-        }
         
-        if (!is_dir($this-&gt;locale_dir) &amp;&amp; !mkdir($this-&gt;locale_dir)) {
+        if (!is_dir($this-&gt;locale_dir) &amp;&amp; !mkdir($this-&gt;locale_dir))
             throw new Exception('locale directory not found and failed to created '.$this-&gt;searchpath);
-        }
     }
     
     function gettext($name, $context) {
+        $gettext = self::$gettext;
         if (!is_string($name)) return ;
         $syntax = '/_\(((?:&quot;.*?&quot;)|(?:\'.*?\'))\)/';
         if (preg_match($syntax, $name, $match)) {
             $text = stripcslashes(substr($match[1], 1, -1));
-            return gettext($text);
+            return call_user_func($gettext, $text);
         }
     }
     
     function setupGettext() {
-        
         if (isset($this-&gt;options['gettext_path']))
             $this-&gt;gettext_path = $this-&gt;options['gettext_path'];
 
@@ -280,13 +288,17 @@ class H2o_I18n {
       }
     }
     
-    function setLocale($locale) {
+    function setLocale($locale, $charset = null) {
         $this-&gt;locale = $locale;
+        if (!$charset)
+            $charset = $this-&gt;charset;
+        
         putenv(&quot;LC_ALL={$locale}&quot;);
         setlocale(LC_ALL, $locale);
         if (!is_dir($this-&gt;locale_dir))
             throw new Exception('Cannot find Locale message path');
         bindtextdomain(&quot;messages&quot;, $this-&gt;locale_dir);
+        bind_textdomain_codeset('messages', $charset);
         textdomain(&quot;messages&quot;);
     }
     </diff>
      <filename>ext/i18n.php</filename>
    </modified>
    <modified>
      <diff>@@ -126,31 +126,25 @@ class H2o_Context implements ArrayAccess {
         foreach ($parts as $part) {
             if (is_array($object) or $object instanceof ArrayAccess) {
                 if (isset($object[$part]))
-                    $object = $object[$part]; 
-                # Support array short cuts
-                elseif (isset($this-&gt;arrayMethods[$part])) {
-                    $size = count($object);
-                    $shortcut = array_combine(
-                        array_flip($this-&gt;arrayMethods), 
-                        array(0, $size - 1, $size, $size)
-                    );
-    
-                    if ($part === 'size' || $part === 'length')
-                        $object = $shortcut[$part];
-                    else
-                        $object = $object[$shortcut[$part]];
-                } 
+                    $object =&amp; $object[$part];
+                elseif ($part === 'first')
+                    $object =&amp; $object[0];
+                elseif ($part === 'last')
+                    $object =&amp; $object[count($object) -1];
+                elseif ($part === 'size' or $part === 'length')
+                    return count($object);
                 else return null;
             }
             elseif (is_object($object)) {
-                $classAllowed =  in_array(get_class($object), $this-&gt;safeClass) || 
-                                 (isset($object-&gt;h2o_safe) &amp;&amp; true === $object-&gt;h2o_safe) ||
-                                   (isset($object-&gt;h2o_safe) &amp;&amp; in_array($part, $object-&gt;h2o_safe));
-
-                if (is_callable(array($object, $part)) &amp;&amp; $classAllowed) {
-                    $object = $object-&gt;$part();
-                } elseif (property_exists($object, $part)) {
+                if (isset($object-&gt;$part))
                     $object = $object-&gt;$part;
+                elseif (is_callable(array($object, $part))) {
+                    $methodAllowed = in_array(get_class($object), $this-&gt;safeClass) || 
+                        (isset($object-&gt;h2o_safe) &amp;&amp; (
+                            $object-&gt;h2o_safe === true || in_array($part, $object-&gt;h2o_safe)
+                        )
+                    );
+                    $object = $methodAllowed ? $object-&gt;$part() : null;
                 }
                 else return null;
             }</diff>
      <filename>h2o/context.php</filename>
    </modified>
    <modified>
      <diff>@@ -165,7 +165,7 @@ class H2O_RE {
         self::$filter_end   = '/;/';
         self::$seperator    = '/,/';
         self::$pipe         = '/\|/';
-        self::$operator     = '/\s?(&gt;|&lt;|&gt;=|&lt;=|!=|==|!|and|not|or)\s?/i';
+        self::$operator     = '/\s?(&gt;|&lt;|&gt;=|&lt;=|!=|==|!|and |not |or )\s?/i';
         self::$number       = '/\d+(\.\d*)?/';
         self::$name         = '/[a-zA-Z][a-zA-Z0-9-_]*(?:\.[a-zA-Z_0-9][a-zA-Z0-9_-]*)*/';
         </diff>
      <filename>h2o/parser.php</filename>
    </modified>
    <modified>
      <diff>@@ -63,6 +63,13 @@ class Describe_Argument_Lexer extends SimpleSpec {
         expects($result)-&gt;should_be($expected);
     }
     
+    function should_parse_variable_contains_operators() {
+        expects($this-&gt;parse(&quot;org&quot;))-&gt;should_be(array(':org'));
+        expects($this-&gt;parse(&quot;dand&quot;))-&gt;should_be(array(':dand'));
+        expects($this-&gt;parse(&quot;xor&quot;))-&gt;should_be(array(':xor'));
+        expects($this-&gt;parse(&quot;notd&quot;))-&gt;should_be(array(':notd'));
+    }
+    
     private function parse($string) {
         return H2o_Parser::parseArguments($string);
     }</diff>
      <filename>specs/parser_spec.php</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>34bee1be3d4f166eabe9fd2334e87ff47c42b9c7</id>
    </parent>
  </parents>
  <author>
    <name>speedmax</name>
    <email>subjective@gmail.com</email>
  </author>
  <url>http://github.com/speedmax/h2o-php/commit/dbda6853f6660c0f76f9b02d570b87839cb02618</url>
  <id>dbda6853f6660c0f76f9b02d570b87839cb02618</id>
  <committed-date>2009-02-16T23:35:59-08:00</committed-date>
  <authored-date>2009-02-16T23:35:59-08:00</authored-date>
  <message>Improve i18n and chartset handling and performance optimization on context lookup

 - Optimize variable context lookup in main H2o_Context::getVariable() method, now context lookup is about 10% faster
 - Adding charset options for i18n support, updated example/i18n
 - Fixed issue where bind_textdomain_codeset call was missing for php-gettext to return string with properly encoding [#7 state:resolved]
 - Adding H2o_I18n::$gettext and H2o_I18n::$ngettext overidable static callbacks to allow usage of custom gettext lookup solution, such as pure php gettext implementations (gettext-php, cakephp I18n class) [#6 state:resolved]
 - Fixed a bug when using customized php-gettext solution where ngettext doesn't work for singular translation in blocktrans tag</message>
  <tree>18a1eb174bc9057463852e21ec7addb486da6157</tree>
  <committer>
    <name>speedmax</name>
    <email>subjective@gmail.com</email>
  </committer>
</commit>
