Subversion-Projekte lars-tiefland.php_share

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
1 lars 1
<?php
2
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
3
 
4
/**
5
 * Contains the Translation2 base class
6
 *
7
 * PHP versions 4 and 5
8
 *
9
 * LICENSE: Redistribution and use in source and binary forms, with or without
10
 * modification, are permitted provided that the following conditions are met:
11
 * 1. Redistributions of source code must retain the above copyright
12
 *    notice, this list of conditions and the following disclaimer.
13
 * 2. Redistributions in binary form must reproduce the above copyright
14
 *    notice, this list of conditions and the following disclaimer in the
15
 *    documentation and/or other materials provided with the distribution.
16
 * 3. The name of the author may not be used to endorse or promote products
17
 *    derived from this software without specific prior written permission.
18
 *
19
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED
20
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22
 * IN NO EVENT SHALL THE FREEBSD PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY
23
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
 *
30
 * @category  Internationalization
31
 * @package   Translation2
32
 * @author    Lorenzo Alberton <l.alberton@quipo.it>
33
 * @copyright 2004-2008 Lorenzo Alberton
34
 * @license   http://www.debian.org/misc/bsd.license  BSD License (3 Clause)
35
 * @version   CVS: $Id: Translation2.php 268999 2008-11-14 16:18:50Z quipo $
36
 * @link      http://pear.php.net/package/Translation2
37
 */
38
 
39
/**
40
 * require PEAR base class
41
 */
42
require_once 'PEAR.php';
43
 
44
/**
45
 * Allows redefinition of the default pageID.
46
 * This constant is needed to allow both NULL and EMPTY pageID values
47
 * and to have them match
48
 */
49
if (!defined('TRANSLATION2_DEFAULT_PAGEID')) {
50
    define('TRANSLATION2_DEFAULT_PAGEID', 'translation2_default_pageID');
51
}
52
/**
53
 * Class Error codes
54
 */
55
define('TRANSLATION2_ERROR',                      -1);
56
define('TRANSLATION2_ERROR_METHOD_NOT_SUPPORTED', -2);
57
define('TRANSLATION2_ERROR_CANNOT_CONNECT',       -3);
58
define('TRANSLATION2_ERROR_CANNOT_FIND_FILE',     -4);
59
define('TRANSLATION2_ERROR_DOMAIN_NOT_SET',       -5);
60
define('TRANSLATION2_ERROR_INVALID_PATH',         -6);
61
define('TRANSLATION2_ERROR_CANNOT_CREATE_DIR',    -7);
62
define('TRANSLATION2_ERROR_CANNOT_WRITE_FILE',    -8);
63
define('TRANSLATION2_ERROR_UNKNOWN_LANG',         -9);
64
define('TRANSLATION2_ERROR_ENCODING_CONVERSION', -10);
65
define('TRANSLATION2_ERROR_UNSUPPORTED',         -11);
66
 
67
/**
68
 * Translation2 base class
69
 *
70
 * This class provides an easy way to retrieve all the strings
71
 * for a multilingual site or application from a data source
72
 * (i.e. a db, an xml file or a gettext file).
73
 *
74
 * @category  Internationalization
75
 * @package   Translation2
76
 * @author    Lorenzo Alberton <l.alberton@quipo.it>
77
 * @copyright 2004-2008 Lorenzo Alberton
78
 * @license   http://www.debian.org/misc/bsd.license  BSD License (3 Clause)
79
 * @link      http://pear.php.net/package/Translation2
80
 */
81
class Translation2
82
{
83
    // {{{ class vars
84
 
85
    /**
86
     * Storage object
87
     * @var object
88
     * @access protected
89
     */
90
    var $storage = '';
91
 
92
    /**
93
     * Class options
94
     * @var array
95
     */
96
    var $options = array();
97
 
98
    /**
99
     * Default lang
100
     * @var array
101
     * @access protected
102
     */
103
    var $lang = array();
104
 
105
    /**
106
     * Current pageID
107
     * @var string
108
     * @access protected
109
     */
110
    var $currentPageID = null;
111
 
112
    /**
113
     * Array of parameters for the adapter class
114
     * @var array
115
     * @access protected
116
     */
117
    var $params = array();
118
 
119
    // }}}
120
    // {{{ Constructor
121
 
122
    /**
123
     * Constructor
124
     */
125
    function Translation2()
126
    {
127
        if (func_num_args()) {
128
            $msg = '<b>Translation2 error:</b>'
129
                  .' Don\'t use the constructor - use factory()';
130
            trigger_error($msg, E_USER_ERROR);
131
        }
132
    }
133
 
134
    // }}}
135
    // {{{ factory()
136
 
137
    /**
138
     * Return a Translation2 instance already initialized
139
     *
140
     * @param string $driver  Type of the storage driver
141
     * @param mixed  $options Additional options for the storage driver
142
     *                        (example: if you are using DB as the storage
143
     *                        driver, you have to pass the dsn string here)
144
     * @param array  $params  Array of parameters for the adapter class
145
     *                        (i.e. you can set here the mappings between your
146
     *                        table/field names and the ones used by this class)
147
     *
148
     * @return object Translation2 instance or PEAR_Error on failure
149
     * @static
150
     */
151
    function & factory($driver, $options = '', $params = array())
152
    {
153
        $tr = new Translation2;
154
        $tr->storage = Translation2::_storageFactory($driver, $options);
155
        if (PEAR::isError($tr->storage)) {
156
            return $tr->storage;
157
        }
158
        $tr->_setDefaultOptions();
159
        $tr->_parseOptions($params);
160
        $tr->storage->_parseOptions($params);
161
        return $tr;
162
    }
163
 
164
    // }}}
165
    // {{{ _storageFactory()
166
 
167
    /**
168
     * Return a storage driver based on $driver and $options
169
     *
170
     * @param string $driver  Type of storage class to return
171
     * @param string $options Optional parameters for the storage class
172
     *
173
     * @return object Object   Storage object
174
     * @static
175
     * @access private
176
     */
177
    function & _storageFactory($driver, $options = '')
178
    {
179
        $storage_path  = 'Translation2/Container/'.strtolower($driver).'.php';
180
        $storage_class = 'Translation2_Container_'.strtolower($driver);
181
        include_once $storage_path;
182
        $storage = new $storage_class;
183
        $err = $storage->init($options);
184
        if (PEAR::isError($err)) {
185
            return $err;
186
        }
187
        return $storage;
188
    }
189
 
190
    // }}}
191
    // {{{ setContainerOptions()
192
 
193
    /**
194
     * Set some storage driver options
195
     *
196
     * @param array $options array of options
197
     *
198
     * @return void
199
     * @access protected
200
     */
201
    function setContainerOptions($options)
202
    {
203
        $this->storage->_parseOptions($options);
204
    }
205
 
206
    // }}}
207
    // {{{ _setDefaultOptions()
208
 
209
    /**
210
     * Set some default options
211
     *
212
     * @return void
213
     * @access private
214
     */
215
    function _setDefaultOptions()
216
    {
217
        $this->options['ParameterPrefix']   = '&&';
218
        $this->options['ParameterPostfix']  = '&&';
219
        $this->options['ParameterAutoFree'] = true;
220
        $this->options['prefetch']          = true;
221
    }
222
 
223
    // }}}
224
    // {{{ _parseOptions()
225
 
226
    /**
227
     * Parse options passed to the base class
228
     *
229
     * @param array $array options
230
     *
231
     * @return void
232
     * @access private
233
     */
234
    function _parseOptions($array)
235
    {
236
        foreach ($array as $key => $value) {
237
            if (isset($this->options[$key])) {
238
                $this->options[$key] = $value;
239
            }
240
        }
241
    }
242
 
243
    // }}}
244
    // {{{ getDecorator()
245
 
246
    /**
247
     * Return an instance of a decorator
248
     *
249
     * This method is used to get a decorator instance.
250
     * A decorator can be seen as a filter, i.e. something that can change
251
     * or handle the values of the objects/vars that pass through.
252
     *
253
     * @param string $decorator Name of the decorator
254
     *
255
     * @return object Decorator object reference
256
     */
257
    function & getDecorator($decorator)
258
    {
259
        $decorator_path  = 'Translation2/Decorator/'.$decorator.'.php';
260
        $decorator_class = 'Translation2_Decorator_'.$decorator;
261
        include_once $decorator_path;
262
        if (func_num_args() > 1) {
263
            $obj = func_get_arg(1);
264
            $new_decorator = new $decorator_class($obj);
265
        } else {
266
            $new_decorator = new $decorator_class($this);
267
        }
268
        return $new_decorator;
269
    }
270
 
271
    // }}}
272
    // {{{ setCharset()
273
 
274
    /**
275
     * Set charset used to read/store the translations
276
     *
277
     * @param string $charset character set (encoding)
278
     *
279
     * @return void|PEAR_Error
280
     */
281
    function setCharset($charset)
282
    {
283
        $res = $this->storage->setCharset($charset);
284
        if (PEAR::isError($res)) {
285
            return $res;
286
        }
287
    }
288
 
289
    // }}}
290
    // {{{ setLang()
291
 
292
    /**
293
     * Set default lang
294
     *
295
     * Set the language that shall be used when retrieving strings.
296
     *
297
     * @param string $langID language code (for instance, 'en' or 'it')
298
     *
299
     * @return true|PEAR_Error
300
     */
301
    function setLang($langID)
302
    {
303
        $res = $this->storage->setLang($langID);
304
        if (PEAR::isError($res)) {
305
            return $res;
306
        }
307
        $this->lang = $res;
308
        return true;
309
    }
310
 
311
    // }}}
312
    // {{{ setPageID($pageID)
313
 
314
    /**
315
     * Set default page
316
     *
317
     * Set the page (aka "group of strings") that shall be used when retrieving strings.
318
     * If you set it, you don't have to state it in each get() call.
319
     *
320
     * @param string $pageID ID of the default page
321
     *
322
     * @return self
323
     */
324
    function setPageID($pageID = null)
325
    {
326
        $this->currentPageID = $pageID;
327
        return $this;
328
    }
329
 
330
    // }}}
331
    // {{{ getLang()
332
 
333
    /**
334
     * get lang info
335
     *
336
     * Get some extra information about the language (its full name,
337
     * the localized error text, ...)
338
     *
339
     * @param string $langID language ID
340
     * @param string $format ['name', 'meta', 'error_text', 'array']
341
     *
342
     * @return mixed [string | array], depending on $format
343
     */
344
    function getLang($langID = null, $format = 'name')
345
    {
346
        if (is_null($langID)) {
347
            if (!isset($this->lang['id'])) {
348
                $msg = 'Translation2::getLang(): unknown language "'.$langID.'".'
349
                      .' Use Translation2::setLang() to set a default language.';
350
                return $this->storage->raiseError($msg, TRANSLATION2_ERROR_UNKNOWN_LANG);
351
            }
352
            $langID = $this->lang['id'];
353
        }
354
        $lang = $this->storage->getLangData($langID);
355
        if ($format == 'array') {
356
            return $lang;
357
        } elseif (isset($lang[$format])) {
358
            return $lang[$format];
359
        } elseif (isset($lang['name'])) {
360
            return $lang['name'];
361
        }
362
        $msg = 'Translation2::getLang(): unknown language "'.$langID.'".'
363
              .' Use Translation2::setLang() to set a default language.';
364
        return $this->storage->raiseError($msg, TRANSLATION2_ERROR_UNKNOWN_LANG);
365
    }
366
 
367
    // }}}
368
    // {{{ getLangs()
369
 
370
    /**
371
     * get langs
372
     *
373
     * Get some extra information about the languages (their full names,
374
     * the localized error text, their codes, ...)
375
     *
376
     * @param string $format ['ids', 'names', 'array']
377
     *
378
     * @return array|PEAR_Error
379
     */
380
    function getLangs($format = 'name')
381
    {
382
        return $this->storage->getLangs($format);
383
    }
384
 
385
    // }}}
386
    // {{{ setParams()
387
 
388
    /**
389
     * Set parameters for next string
390
     *
391
     * Set the replacement for the parameters in the string(s).
392
     * Parameter delimiters are customizable.
393
     *
394
     * @param array $params array of replacement parameters
395
     *
396
     * @return self
397
     */
398
    function setParams($params = null)
399
    {
400
        if (empty($params)) {
401
            $this->params = array();
402
        } elseif (is_array($params)) {
403
            $this->params = $params;
404
        } else {
405
            $this->params = array($params);
406
        }
407
        return $this;
408
    }
409
 
410
    // }}}
411
    // {{{ _replaceParams()
412
 
413
    /**
414
     * Replace parameters in strings
415
     *
416
     * @param mixed $strings strings where the replacements must occur
417
     *
418
     * @return mixed
419
     * @access protected
420
     */
421
    function _replaceParams($strings)
422
    {
423
        if (empty($strings) || is_object($strings) || !count($this->params)) {
424
            return $strings;
425
        }
426
        if (is_array($strings)) {
427
            foreach ($strings as $key => $string) {
428
                $strings[$key] = $this->_replaceParams($string);
429
            }
430
        } else {
431
            if (strpos($strings, $this->options['ParameterPrefix']) !== false) {
432
                foreach ($this->params as $name => $value) {
433
                    $strings = str_replace($this->options['ParameterPrefix']
434
                                           . $name . $this->options['ParameterPostfix'],
435
                                           $value,
436
                                           $strings);
437
                }
438
                if ($this->options['ParameterAutoFree']) {
439
                    $this->params = array();
440
                }
441
            }
442
        }
443
        return $strings;
444
    }
445
 
446
    // }}}
447
    // {{{ replaceEmptyStringsWithKeys()
448
 
449
    /**
450
     * Replace empty strings with their stringID
451
     *
452
     * @param array $strings array of strings to be replaced if empty
453
     *
454
     * @return array
455
     * @static
456
     */
457
    function replaceEmptyStringsWithKeys($strings)
458
    {
459
        if (!is_array($strings)) {
460
            return $strings;
461
        }
462
        foreach ($strings as $key => $string) {
463
            if (empty($string)) {
464
                $strings[$key] = $key;
465
            }
466
        }
467
        return $strings;
468
    }
469
 
470
    // }}}
471
    // {{{ getRaw()
472
 
473
    /**
474
     * Get translated string (as-is)
475
     *
476
     * @param string $stringID    ID of the string to be translated
477
     * @param string $pageID      ID of the page/group containing the string
478
     * @param string $langID      ID of the language
479
     * @param string $defaultText Text to display when the string is empty
480
     *
481
     * @return string|PEAR_Error
482
     */
483
    function getRaw($stringID, $pageID = TRANSLATION2_DEFAULT_PAGEID, $langID = null, $defaultText = '')
484
    {
485
        $pageID = ($pageID == TRANSLATION2_DEFAULT_PAGEID ? $this->currentPageID : $pageID);
486
        $str = $this->storage->getOne($stringID, $pageID, $langID);
487
        if (empty($str)) {
488
            $str = $defaultText;
489
        }
490
        return $str;
491
    }
492
 
493
    // }}}
494
    // {{{ get()
495
 
496
    /**
497
     * Get translated string
498
     *
499
     * First check if the string is cached, if not => fetch the page
500
     * from the container and cache it for later use.
501
     * If the string is empty, check the fallback language; if
502
     * the latter is empty too, then return the $defaultText.
503
     *
504
     * @param string $stringID    ID of the string
505
     * @param string $pageID      ID of the page/group containing the string
506
     * @param string $langID      ID of the language
507
     * @param string $defaultText Text to display when the string is empty
508
     *               NB: This parameter is only used in the DefaultText decorator
509
     *
510
     * @return string
511
     */
512
    function get($stringID, $pageID = TRANSLATION2_DEFAULT_PAGEID, $langID = null, $defaultText = '')
513
    {
514
        $str = $this->getRaw($stringID, $pageID, $langID);
515
        if (PEAR::isError($str)) {
516
            return $str;
517
        }
518
        return $this->_replaceParams($str);
519
    }
520
 
521
    // }}}
522
    // {{{ getRawPage()
523
 
524
    /**
525
     * Get the array of strings in a page
526
     *
527
     * Fetch the page (aka "group of strings) from the container,
528
     * without applying any formatting and without replacing the parameters
529
     *
530
     * @param string $pageID ID of the page/group containing the string
531
     * @param string $langID ID of the language
532
     *
533
     * @return array
534
     */
535
    function getRawPage($pageID = TRANSLATION2_DEFAULT_PAGEID, $langID = null)
536
    {
537
        $pageID = ($pageID == TRANSLATION2_DEFAULT_PAGEID ? $this->currentPageID : $pageID);
538
        return $this->storage->getPage($pageID, $langID);
539
    }
540
 
541
    // }}}
542
    // {{{ getPage()
543
 
544
    /**
545
     * Get an entire group of strings
546
     *
547
     * Same as getRawPage, but resort to fallback language and
548
     * replace parameters when needed
549
     *
550
     * @param string $pageID ID of the page/group containing the string
551
     * @param string $langID ID of the language
552
     *
553
     * @return array
554
     */
555
    function getPage($pageID = TRANSLATION2_DEFAULT_PAGEID, $langID = null)
556
    {
557
        $pageData = $this->getRawPage($pageID, $langID);
558
        return $this->_replaceParams($pageData);
559
    }
560
 
561
    // }}}
562
    // {{{ getStringID()
563
 
564
    /**
565
     * Get the stringID for the given string. This method is the reverse of get().
566
     *
567
     * @param string $string This is NOT the stringID, this is a real string.
568
     *               The method will search for its matching stringID, and then
569
     *               it will return the associate string in the selected language.
570
     * @param string $pageID ID of the page/group containing the string
571
     *
572
     * @return string
573
     */
574
    function getStringID($string, $pageID = TRANSLATION2_DEFAULT_PAGEID)
575
    {
576
        $pageID = ($pageID == TRANSLATION2_DEFAULT_PAGEID ? $this->currentPageID : $pageID);
577
        return $this->storage->getStringID($string, $pageID);
578
    }
579
 
580
    // }}}
581
    // {{{ __clone()
582
 
583
    /**
584
     * Clone internal object references
585
     *
586
     * This method is called automatically by PHP5
587
     *
588
     * @return void
589
     * @access protected
590
     */
591
    function __clone()
592
    {
593
        $this->storage = clone($this->storage);
594
    }
595
 
596
    // }}}
597
}
598
?>