Development

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

You must first sign up to be able to contribute.

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

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