]> git.sur5r.net Git - bacula/bacula/blob - gui/baculum/framework/I18N/core/MessageSource.php
baculum: New Baculum API and Baculum Web
[bacula/bacula] / gui / baculum / framework / I18N / core / MessageSource.php
1 <?php
2
3 /**
4  * MessageSource 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 $Revision: 1.4 $  $Date: 2005/12/17 06:11:28 $
17  * @package System.I18N.core
18  */
19
20  /**
21   * Get the IMessageSource interface.
22   */
23 require_once(dirname(__FILE__).'/IMessageSource.php');
24
25 /**
26  * Get the MessageCache class file.
27  */
28 require_once(dirname(__FILE__).'/MessageCache.php');
29
30 /**
31  * Abstract MessageSource class.
32  * 
33  * The base class for all MessageSources. Message sources must be instantiated
34  * using the factory method. The default valid sources are
35  *
36  *  # XLIFF -- using XML XLIFF format to store the translation messages.
37  *  # gettext -- Translated messages are stored in the gettext format.
38  *  # Database -- Use an existing TDbConnection to store the messages.
39  *  # SQLite -- (Deprecated) Store the translation messages in a SQLite database.
40  *
41  * A custom message source can be instantiated by specifying the filename
42  * parameter to point to the custom class file. E.g.
43  * <code>
44  *   $resource = '...'; //custom message source resource
45  *   $classfile = '../MessageSource_MySource.php'; //custom message source
46  *   $source = MessageSource::factory('MySource', $resource, $classfile);
47  * </code>
48  * 
49  * If you are writting your own message sources, pay attention to the 
50  * loadCatalogue method. It details how the resources are loaded and cached.
51  * See also the existing message source types as examples.
52  * 
53  * The following example instantiates a Database message source, set the culture,
54  * set the cache handler, and use the source in a message formatter. 
55  * The messages are stored using an existing connection. The source parameter
56  * for the factory method must contain a valid ConnectionID.
57  * <code>
58  *   // db1 must be already configured
59  *   $source = MessageSource::factory('Database', 'db1');
60  *   
61  *   //set the culture and cache, store the cache in the /tmp directory.
62  *   $source->setCulture('en_AU')l
63  *   $source->setCache(new MessageCache('/tmp'));
64  *   
65  *   $formatter = new MessageFormat($source);
66  * </code>
67  *
68  * @author Xiang Wei Zhuo <weizhuo[at]gmail[dot]com>
69  * @version v1.0, last update on Fri Dec 24 19:55:49 EST 2004
70  * @package System.I18N.core
71  */
72 abstract class MessageSource implements IMessageSource
73 {       
74         /**
75          * The culture name for this message source.
76          * @var string 
77          */
78         protected $culture;
79         
80         /**
81          * Array of translation messages.
82          * @var array 
83          */
84         protected $messages = array();
85
86         /**
87          * The source of message translations.
88          * @var string 
89          */
90         protected $source;
91         
92         /**
93          * The translation cache.
94          * @var MessageCache 
95          */
96         protected $cache;
97         
98         protected $untranslated = array();
99
100         /**
101          * Private constructor. MessageSource must be initialized using
102          * the factory method.
103          */
104         private function __construct()
105         {       
106                 //throw new Exception('Please use the factory method to instantiate.');
107         }
108         
109         /**
110          * Factory method to instantiate a new MessageSource depending on the
111          * source type. The allowed source types are 'XLIFF', 'gettext' and
112      * 'Database'. The source parameter depends on the source type. 
113      * For 'gettext' and 'XLIFF', 'source' should point to the directory 
114      * where the messages are stored. 
115      * For 'Database', 'source' must be a valid connection id.
116      * If a deprecated 'SQLite' type is used, 'source' must contain
117      * a valid DSN.
118          *
119          * Custom message source are possible by supplying the a filename parameter
120          * in the factory method.
121          * 
122          * @param string the message source type.
123          * @param string the location of the resource or the ConnectionID.
124          * @param string the filename of the custom message source.
125          * @return MessageSource a new message source of the specified type. 
126          * @throws InvalidMessageSourceTypeException
127          */
128         static function &factory($type, $source='.', $filename='')
129         {
130                 $types = array('XLIFF','gettext','Database','SQLite');
131
132                 if(empty($filename) && !in_array($type, $types))
133                         throw new Exception('Invalid type "'.$type.'", valid types are '.
134                                 implode(', ', $types));
135                 
136                 $class = 'MessageSource_'.$type;
137                 
138                 if(empty($filename))
139                         $filename = dirname(__FILE__).'/'.$class.'.php';
140                                                 
141                 if(is_file($filename) == false)
142                         throw new Exception("File $filename not found");
143                                                 
144                 include_once $filename;
145         
146                 $obj =  new $class($source);
147                 
148                 return $obj;
149         }
150         
151         /**
152          * Load a particular message catalogue. Use read() to 
153          * to get the array of messages. The catalogue loading sequence
154          * is as follows
155          *
156          *  # [1] call getCatalogeList($catalogue) to get a list of 
157          *    variants for for the specified $catalogue.
158          *  # [2] for each of the variants, call getSource($variant)
159          *    to get the resource, could be a file or catalogue ID.
160          *  # [3] verify that this resource is valid by calling isValidSource($source)
161          *  # [4] try to get the messages from the cache
162          *  # [5] if a cache miss, call load($source) to load the message array
163          *  # [6] store the messages to cache.
164          *  # [7] continue with the foreach loop, e.g. goto [2].
165          * 
166          * @param string a catalogue to load
167          * @return boolean true if loaded, false otherwise.      
168          * @see read()
169          */
170         function load($catalogue='messages')
171         {
172                 $variants = $this->getCatalogueList($catalogue);
173                 
174                 $this->messages = array();
175                 
176                 foreach($variants as $variant)
177                 {
178                         $source = $this->getSource($variant);
179                         
180                         if($this->isValidSource($source) == false) continue;
181
182                         $loadData = true;
183                         
184                         if($this->cache)
185                         {
186                                 $data = $this->cache->get($variant, 
187                                         $this->culture, $this->getLastModified($source));
188                                 
189                                 if(is_array($data))
190                                 {
191                                         $this->messages[$variant] = $data;
192                                         $loadData = false;
193                                 }
194                                 unset($data);
195                         }
196                         if($loadData)
197                         {
198                                 $data = &$this->loadData($source);
199                                 if(is_array($data))
200                                 {
201                                         $this->messages[$variant] = $data;
202                                         if($this->cache)
203                                                 $this->cache->save($data, $variant, $this->culture);
204                                 }       
205                                 unset($data);
206                         }
207                 }
208                 
209                 return true;
210         }       
211         
212         /**
213          * Get the array of messages.
214          * @param parameter
215          * @return array translation messages. 
216          */
217         public function read()
218         {
219                 return $this->messages;
220         }
221                 
222         /**
223          * Get the cache handler for this source.
224          * @return MessageCache cache handler
225          */
226         public function getCache()
227         {
228                 return $this->cache;
229         }
230         
231         /**
232          * Set the cache handler for caching the messages.
233          * @param MessageCache the cache handler.
234          */
235         public function setCache(MessageCache $cache)
236         {
237                 $this->cache = $cache;
238         }
239         
240         /**
241          * Add a untranslated message to the source. Need to call save()
242          * to save the messages to source.
243          * @param string message to add
244          */     
245         public function append($message)
246         {
247                 if(!in_array($message, $this->untranslated))
248                         $this->untranslated[] = $message;
249         }
250         
251         /**
252          * Set the culture for this message source.
253          * @param string culture name
254          */
255         public function setCulture($culture)
256         {
257                 $this->culture = $culture;
258         }       
259         
260         /**
261          * Get the culture identifier for the source.
262          * @return string culture identifier. 
263          */
264         public function getCulture()
265         {
266                 return $this->culture;
267         }       
268
269         /**
270          * Get the last modified unix-time for this particular catalogue+variant.
271          * @param string catalogue+variant
272          * @return int last modified in unix-time format.
273          */
274         protected function getLastModified($source)
275         {
276                 return 0;
277         }
278         
279         /**
280          * Load the message for a particular catalogue+variant.
281          * This methods needs to implemented by subclasses.
282          * @param string catalogue+variant.
283          * @return array of translation messages. 
284          */
285         protected function &loadData($variant)
286         {
287                 return array();
288         }
289         
290         /**
291          * Get the source, this could be a filename or database ID.
292          * @param string catalogue+variant
293          * @return string the resource key 
294          */
295         protected function getSource($variant)
296         {
297                 return $variant;
298         }
299         
300         /**
301          * Determine if the source is valid.
302          * @param string catalogue+variant
303          * @return boolean true if valid, false otherwise. 
304          */
305         protected function isValidSource($source)
306         {
307                 return false;
308         }
309         
310         /**
311          * Get all the variants of a particular catalogue.
312          * This method must be implemented by subclasses.
313          * @param string catalogue name
314          * @return array list of all variants for this catalogue. 
315          */     
316         protected function getCatalogueList($catalogue)
317         {
318                 return array();
319         }               
320 }
321
322
323 /**
324  * TMessageSourceIOException thrown when unable to modify message source
325  * data.
326  *
327  * @author Wei Zhuo<weizhuo[at]gmail[dot]com>
328  * @version $Revision: 1.4 $  $Date: 2005/12/17 06:11:28 ${DATE} ${TIME} $
329  * @package System.I18N.core
330  */
331 class TMessageSourceIOException extends TException
332 {
333
334 }