fix image text
[pear] / I18Nv2 / Negotiator.php
1 <?php
2 // +----------------------------------------------------------------------+
3 // | PEAR :: I18Nv2 :: Negotiator                                         |
4 // +----------------------------------------------------------------------+
5 // | This source file is subject to version 3.0 of the PHP license,       |
6 // | that is available at http://www.php.net/license/3_0.txt              |
7 // | If you did not receive a copy of the PHP license and are unable      |
8 // | to obtain it through the world-wide-web, please send a note to       |
9 // | license@php.net so we can mail you a copy immediately.               |
10 // +----------------------------------------------------------------------+
11 // | Copyright (c) 2004 The Authors                                       |
12 // +----------------------------------------------------------------------+
13 // | Authors:   Naoki Shima <murahachibu@php.net>                         |
14 // |            Wolfram Kriesing <wk@visionp.de>                          |
15 // |            Michael Wallner <mike@iworks.at>                          |
16 // +----------------------------------------------------------------------+
17 //
18 // $Id: Negotiator.php,v 1.11 2005/11/28 15:33:22 mike Exp $
19
20 /**
21  * I18Nv2::Negotiator
22  *
23  * @package      I18Nv2
24  * @category     Internationalization
25  */
26
27 /**
28  * I18Nv2_Negotiator
29  * 
30  * @author      Naoki Shima <murahachibu@php.net>
31  * @author      Wolfram Kriesing <wk@visionp.de>
32  * @author      Michael Wallner <mike@php.net>
33  * @version     $Revision: 1.11 $
34  * @access      public
35  * @package     I18Nv2
36  */
37 class I18Nv2_Negotiator
38 {
39     /**
40      * I18Nv2_Language
41      * 
42      * @var     object
43      * @access  public
44      */
45     var $I18NLang = null;
46     
47     /**
48      * I18Nv2_Country
49      * 
50      * @var     object
51      * @access  public
52      */
53     var $I18NCountry = null;
54     
55     /**
56      * Save default country code.
57      *
58      * @var     string
59      * @access  private
60      */
61     var $_defaultCountry;
62
63     /**
64      * Save default language code.
65      *
66      * @var     string
67      * @access  private
68      */
69     var $_defaultLanguage;
70
71     /**
72      * Save default encoding code.
73      *
74      * @var     string
75      * @access  private
76      */
77     var $_defaultEncoding;
78
79     /**
80      * HTTP_ACCEPT_CHARSET
81      * 
82      * @var     array
83      * @access  private
84      */
85     var $_acceptEncoding = array();
86     
87     /**
88      * HTTP_ACCEPT_LANGUAGE
89      * 
90      * @var     array
91      * @access  private
92      */
93     var $_acceptLanguage = array();
94     
95     /**
96      * Language variations
97      * 
98      * @var     array
99      * @access  private
100      */
101     var $_langVariation = array();
102     
103     /**
104      * Countries
105      * 
106      * @var     array
107      * @access  private
108      */
109     var $_country = array();
110     
111     /**
112      * Constructor
113      * 
114      * Find language code, country code, encoding code, and dialect or variant
115      * of Locale setting in HTTP request headers.
116      *
117      * @access  public
118      * @param   string  $defaultLanguage    Default Language
119      * @param   string  $defaultEncoding    Default Encoding
120      * @param   string  $defaultCountry     Default Country
121      */
122     function I18Nv2_Negotiator($defaultLanguage = 'en', $defaultEncoding = 'iso-8859-1', $defaultCountry = '')
123     {
124         $this->__construct($defaultLanguage, $defaultEncoding, $defaultCountry);
125     }
126     
127     /**
128      * ZE2 Constructor
129      * @ignore
130      */
131     function __construct($defaultLanguage = 'en', $defaultEncoding = 'iso-8859-1', $defaultCountry = '')
132     {
133         $this->_defaultCountry  = $defaultCountry;
134         $this->_defaultLanguage = $defaultLanguage;
135         $this->_defaultEncoding  = $defaultEncoding;
136         
137         $this->_negotiateLanguage();
138         $this->_negotiateEncoding();
139     }
140     
141     /**
142      * Negotiate Language
143      *
144      * @access  private
145      * @return  void
146      */
147     function _negotiateLanguage()
148     {
149         if (!isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) {
150             return;
151         }
152         foreach(explode(',', $_SERVER['HTTP_ACCEPT_LANGUAGE']) as $lang) {
153             // Cut off any q-value that might come after a semi-colon
154             if ($pos = strpos($lang, ';')) {
155                 $lang = trim(substr($lang, 0, $pos));
156             }
157             if (strstr($lang, '-')) {
158                 list($pri, $sub) = explode('-', $lang);
159                 if ($pri == 'i') {
160                     /**
161                     * Language not listed in ISO 639 that are not variants
162                     * of any listed language, which can be registerd with the
163                     * i-prefix, such as i-cherokee
164                     */
165                     $lang = $sub;
166                 } else {
167                     $lang = $pri;
168                     $this->singleI18NCountry();
169                     if ($this->I18NCountry->isValidCode($sub)) {
170                         $this->_country[$lang][] = strToUpper($sub);
171                     } else { 
172                         $this->_langVariation[$lang][] = $sub;
173                     }
174                 }
175             }
176             $this->_acceptLanguage[] = $lang;
177         }
178     }
179     
180     /**
181      * Negotiate Encoding
182      *
183      * @access  private
184      * @return  void
185      */
186     function _negotiateEncoding()
187     {
188         if (!isset($_SERVER['HTTP_ACCEPT_CHARSET'])) {
189             return;
190         }
191         foreach (explode(',', $_SERVER['HTTP_ACCEPT_CHARSET']) as $encoding) {
192             if (!empty($encoding)) {
193                 $this->_acceptEncoding[] = preg_replace('/;.*/', '', $encoding);
194             }
195         }
196     }
197     
198     /**
199      * Find Country Match
200      *
201      * @access  public
202      * @return  array
203      * @param   string  $lang
204      * @param   array   $countries
205      */
206     function getCountryMatch($lang, $countries = null)
207     {
208         return $this->_getMatch(
209             $countries,
210             @$this->_country[$lang],
211             $this->_defaultCountry
212         );
213     }
214  
215     /**
216      * Return variant info for passed parameter.
217      *
218      * @access  public
219      * @return  string
220      * @param   string  $lang
221      */
222     function getVariantInfo($lang)
223     {
224         return isset($this->_langVariation[$lang]) ? $this->_langVariation[$lang] : null;
225     }
226
227     /**
228      * Find Encoding match
229      * 
230      * @deprecated
231      * @access  public
232      * @return  string
233      * @param   array   $encodings
234      */
235     function getCharsetMatch($encodings = null)
236     {
237         return $this->_getMatch(
238             $encodings, 
239             $this->_acceptEncoding, 
240             $this->_defaultEncoding
241         );
242     }
243
244     /**
245      * Find Encoding match
246      * 
247      * @access  public
248      * @return  string
249      * @param   array   $encodings
250      */
251     function getEncodingMatch($encodings = null)
252     {
253         return $this->_getMatch(
254             $encodings, 
255             $this->_acceptEncoding, 
256             $this->_defaultEncoding
257         );
258     }
259
260     /**
261      * Find Language match
262      *
263      * @access  public
264      * @return  string
265      * @param   array   $langs
266      */
267     function getLanguageMatch($langs = null)
268     {
269         return $this->_getMatch(
270             $langs, 
271             $this->_acceptLanguage,
272             $this->_defaultLanguage
273         );
274     }
275     
276     /**
277      * Find locale match
278      *
279      * @access  public
280      * @return  string
281      * @param   array   $langs
282      * @param   array   $countries
283      */
284     function getLocaleMatch($langs = null, $countries = null)
285     {
286         $lang = $this->_getMatch($langs, $this->_acceptLanguage, $this->_defaultLanguage);
287         $ctry = $this->_getMatch($countries, @$this->_country[$lang], $this->_defaultCountry);
288         return $lang . ($ctry ? '_' . $ctry : '');
289     }
290     
291     /**
292      * Return first matched value from first and second parameter.
293      * If there is no match found, then return third parameter.
294      * 
295      * @access  private
296      * @return  string
297      * @param   array   $needle
298      * @param   array   $haystack
299      * @param   string  $default
300      */
301     function _getMatch($needle, $haystack, $default = '')
302     {
303         if (!$haystack) {
304             return $default;
305         }
306         if (!$needle) {
307             return current($haystack);
308         }
309         if ($result = current($a = array_intersect($haystack, $needle))) {
310             return $result;
311         }
312         return $default;
313     }
314     
315     /**
316      * Find Country name for country code passed 
317      * 
318      * @access  private
319      * @return  void
320      * @param   string  $code   country code
321      */
322     function getCountryName($code)
323     {
324         $this->singleI18NCountry();
325         return $this->I18NCountry->getName($code);
326     }
327
328     /**
329      * Find Country name for country code passed 
330      * 
331      * @access  private
332      * @return  void
333      * @param   string      $code   language code
334      */
335     function getLanguageName($code)
336     {
337         $this->singleI18NLanguage();
338         return $this->I18NLang->getName($code);
339     }
340
341     /**
342      * Create the Language helper object
343      * 
344      * @access  public
345      * @return  object
346      */
347     function &singleI18NLanguage()
348     {
349         if (!isset($this->I18NLang)) {
350             include_once 'I18Nv2/Language.php';
351             $this->I18NLang = &new I18Nv2_Language(
352                 $this->_defaultLanguage, 
353                 $this->_defaultEncoding
354             );
355         }
356         return $this->I18NLang;
357     }
358
359     /**
360      * Create the Country helper object
361      * 
362      * @access  public
363      * @return  object
364      */
365     function &singleI18NCountry()
366     {
367         if (!isset($this->I18NCountry)) {
368             include_once 'I18Nv2/Country.php';
369             $this->I18NCountry = &new I18Nv2_Country(
370                 $this->_defaultLanguage,
371                 $this->_defaultEncoding
372             );
373         }
374         return $this->I18NCountry;
375     }
376 }
377 ?>