Development

/branches/1.3/lib/i18n/sfMessageFormat.class.php

You must first sign up to be able to contribute.

root/branches/1.3/lib/i18n/sfMessageFormat.class.php

Revision 24622, 6.6 kB (checked in by FabianLange, 4 years ago)

[1.0, 1.2, 1.3, 1.4] allowed __() and sfI18N->__() and sfMessageFormat->format() to take an object with a __toString() method. Test case for 1.2,1.3 and 1.4 (fixes #7559, #6763, refs #2161)

  • Property svn:mime-type set to text/x-php
  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
Line 
1 <?php
2
3 /**
4  * sfMessageFormat class file.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the BSD License.
8  *
9  * Copyright(c) 2004 by Qiang Xue. All rights reserved.
10  *
11  * To contact the author write to {@link mailto:qiang.xue@gmail.com Qiang Xue}
12  * The latest version of PRADO can be obtained from:
13  * {@link http://prado.sourceforge.net/}
14  *
15  * @author     Wei Zhuo <weizhuo[at]gmail[dot]com>
16  * @version    $Id$
17  * @package    symfony
18  * @subpackage i18n
19  */
20
21 /**
22  * sfMessageFormat class.
23  *
24  * Format a message, that is, for a particular message find the
25  * translated message. The following is an example using
26  * a SQLite database to store the translation message.
27  * Create a new message format instance and echo "Hello"
28  * in simplified Chinese. This assumes that the world "Hello"
29  * is translated in the database.
30  *
31  * <code>
32  *  $source = sfMessageSource::factory('SQLite', 'sqlite://messages.db');
33  *  $source->setCulture('zh_CN');
34  *  $source->setCache(new sfMessageCache('./tmp'));
35  *
36  *  $formatter = new sfMessageFormat($source);
37  * 
38  *  echo $formatter->format('Hello');
39  * </code>
40  *
41  * @author Xiang Wei Zhuo <weizhuo[at]gmail[dot]com>
42  * @version v1.0, last update on Fri Dec 24 20:46:16 EST 2004
43  * @package    symfony
44  * @subpackage i18n
45  */
46 class sfMessageFormat
47 {
48   /**
49    * The message source.
50    * @var sfMessageSource
51    */
52   protected $source;
53
54   /**
55    * A list of loaded message catalogues.
56    * @var array
57    */
58   protected $catalogues = array();
59
60   /**
61    * The translation messages.
62    * @var array
63    */
64   protected $messages = array();
65
66   /**
67    * A list of untranslated messages.
68    * @var array
69    */
70   protected $untranslated = array();
71
72   /**
73    * The prefix and suffix to append to untranslated messages.
74    * @var array
75    */
76   protected $postscript = array('', '');
77
78   /**
79    * Set the default catalogue.
80    * @var string
81    */
82   public $catalogue;
83
84   /**
85    * Output encoding charset
86    * @var string
87    */
88   protected $charset = 'UTF-8';
89
90   /**
91    * Constructor.
92    * Create a new instance of sfMessageFormat using the messages
93    * from the supplied message source.
94    *
95    * @param sfMessageSource $source   the source of translation messages.
96    * @param string          $charset  for the message output.
97    */
98   function __construct(sfIMessageSource $source, $charset = 'UTF-8')
99   {
100     $this->source = $source;
101     $this->setCharset($charset);
102   }
103
104   /**
105    * Sets the charset for message output.
106    *
107    * @param string $charset charset, default is UTF-8
108    */
109   public function setCharset($charset)
110   {
111     $this->charset = $charset;
112   }
113
114   /**
115    * Gets the charset for message output. Default is UTF-8.
116    *
117    * @return string charset, default UTF-8
118    */
119   public function getCharset()
120   {
121     return $this->charset;
122   }
123  
124   /**
125    * Loads the message from a particular catalogue. A listed
126    * loaded catalogues is kept to prevent reload of the same
127    * catalogue. The load catalogue messages are stored
128    * in the $this->message array.
129    *
130    * @param string $catalogue message catalogue to load.
131    */
132   protected function loadCatalogue($catalogue)
133   {
134     if (in_array($catalogue, $this->catalogues))
135     {
136       return;
137     }
138
139     if ($this->source->load($catalogue))
140     {
141       $this->messages[$catalogue] = $this->source->read();
142       $this->catalogues[] = $catalogue;
143     }
144   }
145
146   /**
147    * Formats the string. That is, for a particular string find
148    * the corresponding translation. Variable subsitution is performed
149    * for the $args parameter. A different catalogue can be specified
150    * using the $catalogue parameter.
151    * The output charset is determined by $this->getCharset();
152    *
153    * @param string  $string     the string to translate.
154    * @param array   $args       a list of string to substitute.
155    * @param string  $catalogue  get the translation from a particular message
156    * @param string  $charset    charset, the input AND output charset catalogue.
157    * @return string translated string.
158    */
159   public function format($string, $args = array(), $catalogue = null, $charset = null)
160   {
161     // make sure that objects with __toString() are converted to strings
162     $string = (string) $string;
163     if (empty($charset))
164     {
165       $charset = $this->getCharset();
166     }
167
168     $s = $this->formatString(sfToolkit::I18N_toUTF8($string, $charset), $args, $catalogue);
169
170     return sfToolkit::I18N_toEncoding($s, $charset);
171   }
172
173   /**
174    * Do string translation.
175    *
176    * @param string  $string     the string to translate.
177    * @param array   $args       a list of string to substitute.
178    * @param string  $catalogue  get the translation from a particular message catalogue.
179    * @return string translated string.
180    */
181   protected function formatString($string, $args = array(), $catalogue = null)
182   {
183     if (empty($args))
184     {
185       $args = array();
186     }
187
188     if (empty($catalogue))
189     {
190       $catalogue = empty($this->catalogue) ? 'messages' : $this->catalogue;
191     }
192
193     $this->loadCatalogue($catalogue);
194
195     foreach ($this->messages[$catalogue] as $variant)
196     {
197       // we found it, so return the target translation
198       if (isset($variant[$string]))
199       {
200         $target = $variant[$string];
201
202         // check if it contains only strings.
203         if (is_array($target))
204         {
205           $target = array_shift($target);
206         }
207
208         // found, but untranslated
209         if (empty($target))
210         {
211           return $this->postscript[0].$this->replaceArgs($string, $args).$this->postscript[1];
212         }
213         return $this->replaceArgs($target, $args);
214       }
215     }
216
217     // well we did not find the translation string.
218     $this->source->append($string);
219
220     return $this->postscript[0].$this->replaceArgs($string, $args).$this->postscript[1];
221   }
222
223   protected function replaceArgs($string, $args)
224   {
225     // replace object with strings
226     foreach ($args as $key => $value)
227     {
228       if (is_object($value) && method_exists($value, '__toString'))
229       {
230         $args[$key] = $value->__toString();
231       }
232     }
233
234     return strtr($string, $args);
235   }
236
237   /**
238    * Gets the message source.
239    *
240    * @return MessageSource
241    */
242   function getSource()
243   {
244     return $this->source;
245   }
246  
247   /**
248    * Sets the prefix and suffix to append to untranslated messages.
249    * e.g. $postscript=array('[T]','[/T]'); will output
250    * "[T]Hello[/T]" if the translation for "Hello" can not be determined.
251    *
252    * @param array $postscript first element is the prefix, second element the suffix.
253    */
254   function setUntranslatedPS($postscript)
255   {
256     if (is_array($postscript) && count($postscript) >= 2)
257     {
258       $this->postscript[0] = $postscript[0];
259       $this->postscript[1] = $postscript[1];
260     }
261   }
262 }
263
Note: See TracBrowser for help on using the browser.