FusionDirectory
 All Data Structures Files Functions Variables
accept-to-gettext.inc
1 <?php
2 /*
3  * accept-to-gettext.inc -- convert information in 'Accept-*' headers to
4  * gettext language identifiers.
5  * Copyright (c) 2003, Wouter Verhelst <wouter@debian.org>
6  * Copyright (c) 2012-2016, FusionDirectory
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
21  *
22  * Usage:
23  *
24  * $locale=al2gt(<array of supported languages/charsets in gettext syntax>,
25  * <MIME type of document>);
26  * setlocale('LC_ALL', $locale); // or 'LC_MESSAGES', or whatever...
27  *
28  * Example:
29  *
30  * $langs=array('nl_BE.ISO-8859-15','nl_BE.UTF-8','en_US.UTF-8','en_GB.UTF-8');
31  * $locale=al2gt($langs, 'text/html');
32  * setlocale('LC_ALL', $locale);
33  *
34  * Note that this will send out header information (to be
35  * RFC2616-compliant), so it must be called before anything is sent to
36  * the user.
37  *
38  * Assumptions made:
39  * * Charset encodings are written the same way as the Accept-Charset
40  * HTTP header specifies them (RFC2616), except that they're parsed
41  * case-insensitive.
42  * * Country codes and language codes are the same in both gettext and
43  * the Accept-Language syntax (except for the case differences, which
44  * are dealt with easily). If not, some input may be ignored.
45  * * The provided gettext-strings are fully qualified; i.e., no "en_US";
46  * always "en_US.ISO-8859-15" or "en_US.UTF-8", or whichever has been
47  * used. "en.ISO-8859-15" is OK, though.
48  * * The language is more important than the charset; i.e., if the
49  * following is given:
50  *
51  * Accept-Language: nl-be, nl;q=0.8, en-us;q=0.5, en;q=0.3
52  * Accept-Charset: ISO-8859-15, utf-8;q=0.5
53  *
54  * And the supplied parameter contains (amongst others) nl_BE.UTF-8
55  * and nl.ISO-8859-15, then nl_BE.UTF-8 will be picked.
56  *
57  * $Log: accept-to-gettext.inc,v $
58  * Revision 1.1.1.1 2003/11/19 19:31:15 wouter
59  * * moved to new CVS repo after death of the old
60  * * Fixed code to apply a default to both Accept-Charset and
61  * Accept-Language if none of those headers are supplied; patch from
62  * Dominic Chambers <dominic@encasa.com>
63  *
64  * Revision 1.2 2003/08/14 10:23:59 wouter
65  * Removed little error in Content-Type header syntaxis.
66  *
67  * Revision 2012/06/07 Côme BERNIGAUD
68  * Rewrote a lot of things, use functions and PHP features in order to be more efficient and more readable
69  */
70 
75 function parse_scores ($str)
76 {
77  $scores = array();
78  $parts = preg_split('/,/', $str);
79  foreach ($parts as $part) {
80  $part = trim(strtolower($part));
81  if (preg_match("/(.*);q=(.*)/", $part, $matches)) {
82  $scores[$matches[1]] = $matches[2];
83  } else {
84  $scores[$part] = 1;
85  }
86  }
87  return $scores;
88 }
89 
95 function max_scores ($scores, $testvals)
96 {
97  $values = array_intersect_key($scores, array_flip($testvals));
98  if (empty($values)) {
99  return 0;
100  } else {
101  return max($values);
102  }
103 }
104 
109 function parse_gettext_lang ($str)
110 {
111  if (preg_match("/^([^_]*)(_([^_]*))?\.(.*)$/", $str, $m)) {
112  return array(strtolower($m[1]), strtolower($m[3]), strtolower($m[4]));
113  } else {
114  return FALSE;
115  }
116 }
117 
118 function al2gt($gettextlangs, $mime)
119 {
120  /* Check if ACCEPT_LANGUAGE isset */
121  if (empty($_SERVER["HTTP_ACCEPT_LANGUAGE"])) {
122  /* default to "everything is acceptable", as RFC2616 specifies */
123  $acceptLang = '*';
124  } else {
125  $acceptLang = $_SERVER["HTTP_ACCEPT_LANGUAGE"];
126  }
127  if (empty($_SERVER["HTTP_ACCEPT_CHARSET"])) {
128  /* default to "everything is acceptable", as RFC2616 specifies */
129  $acceptChar = 'ISO-8859-1,*;q=0.5';
130  } else {
131  $acceptChar = $_SERVER["HTTP_ACCEPT_CHARSET"];
132  }
133 
134  $lang_scores = parse_scores($acceptLang);
135  $char_scores = parse_scores($acceptChar);
136 
137  /* RFC2616: ``If no "*" is present in an Accept-Charset field, then
138  * all character sets not explicitly mentioned get a quality value of
139  * 0, except for ISO-8859-1, which gets a quality value of 1 if not
140  * explicitly mentioned.'' */
141  if (!isset($char_scores['ISO-8859-1']) && !isset($char_scores['*'])) {
142  $char_scores['ISO-8859-1'] = 1;
143  }
144 
145  /* Loop through the available languages/encodings, and pick the one
146  * with the highest score, excluding the ones with a charset the user
147  * did not include. */
148  // The lang with the maximum score found
149  $max_lang = NULL;
150  // The lang score of this lang
151  $max_l_score = 0;
152  // The char score of this lang
153  $max_c_score = 0;
154  foreach ($gettextlangs as $gtlang) {
155  if (!($infos = parse_gettext_lang($gtlang))) {
156  continue;
157  }
158  list ($lang, $country, $char) = $infos;
159 
160  $lang_score = max_scores($lang_scores, array($lang,$lang.'-'.$country,'*'));
161  $char_score = max_scores($char_scores, array($char,'*'));
162  if ($char_score == 0) {
163  // exclude charsets the user refuses
164  continue;
165  }
166 
167  // if lang scores are equals we compare char scores
168  if (($lang_score > $max_l_score)
169  || (($lang_score == $max_l_score) && ($char_score > $max_c_score))) {
170  $max_l_score = $lang_score;
171  $max_c_score = $char_score;
172  $max_lang = $gtlang;
173  }
174  }
175 
176  if ($max_lang === NULL) {
177  return NULL;
178  }
179 
180  /* We must re-parse the gettext-string now, since we may have found it
181  * through a "*" qualifier.*/
182  list ($lang, $country, $char) = parse_gettext_lang($max_lang);
183  if (!headers_sent()) {
184  header("Content-Language: $lang".(empty($country)?"":"-$country"));
185  if (!empty($char)) {
186  header("Content-Type: $mime; charset=$char");
187  }
188  }
189  return $max_lang;
190 }
191 ?>