Updated for Drupal-HEAD
[project/i18n.git] / i18n.module
1 <?php
2 // $Id$
3
4 /**
5 * Internationalization (i18n) module
6 *
7 * @author Jose A. Reyero, 2004
8 *
9 */
10
11 /**
12 * Module initialization
13 *
14 * Get language from path if exists and Initialize i18n system
15 * May do a redirect from home page for not to get wrong versions in cache
16 */
17
18 function i18n_init(){
19 global $i18n_langpath;
20 // Some functions only to be included when module is enabled
21
22 $path = _i18n_get_original_path();
23 $i18n_langpath = i18n_get_lang_prefix($path);
24 $lang = _i18n_get_lang();
25
26 if ($path == '') { // Main page
27 // Check for update script
28 if (isset($_GET['op'])) {
29 return ;
30 }
31 if( variable_get('cache',0) && $lang != i18n_default_language() ) {
32 // Redirect to main page in $lang
33 _i18n_goto($lang);
34 } elseif (variable_get('i18n_frontpage',0)){
35 $_GET['q'] = i18n_frontpage();
36 }
37 }
38 elseif ($lang == $path) { // When path is only language code
39 $_GET['q'] = variable_get('i18n_frontpage',0) ? i18n_frontpage() : variable_get('site_frontpage','node');
40 }
41 elseif ($i18n_langpath) {
42 //search alias with and without lang and remove lang
43 $_GET['q'] = i18n_get_normal_path($path);
44 }
45
46 // Multi table, for backwards compatibility and experimentation
47 if (variable_get('i18n_multi' , 0)) {
48 _i18n_set_db_prefix(_i18n_get_lang());
49 }
50
51 // If not in bootstrap, include hooks
52 if(!_i18n_is_bootstrap()){
53 include 'modules/i18n/i18n.inc';
54 i18n_variable_init();
55 }
56 }
57
58 /**
59 * Common module functions
60 */
61
62 /**
63 * Implementation of hook_help().
64 */
65 function i18n_help($section = 'admin/help#i18n' ) {
66 switch ($section) {
67 case 'admin/help#i18n' :
68 $output = t('
69 <p>This module provides support for internationalization of Drupal sites:</p>
70 <ul>
71 <li>Translation of the user interface for anonymous users (combined with locale)</li>
72 <li>Multi-language for content. Adds a language field for nodes and taxonomy vocabularies and terms</li>
73 <li>Basic translation management</li>
74 <li>Browser language detection</li>
75 <li>Keeps the language setting accross consecutive requests using URL rewriting</li>
76 <li>Provides a block for language selection and two theme functions: <i>i18n_flags</i> and <i>i18n_links</i></li>
77 <li>Support for long locale names</li>
78 </ul>
79 <p><small>Module developed by Jose A. Reyero, <a href="http://www.reyero.net">www.reyero.net</a></small></p>' );
80 break;
81 case 'admin/modules#description' :
82 $output = t('Enables multilingual content. <b>Requires locale module for interface translation</b>' );
83 break;
84 }
85 return $output;
86 }
87
88 /**
89 * Implementation of hook_settings().
90 */
91 function i18n_settings() {
92 global $db_prefix_i18n;
93 global $i18n_languages;
94 // Basic settings
95 $config_languages = is_array($i18n_languages) ? implode(', ',$i18n_languages) : 'Not defined';
96 $output .= form_radios(t('Supported languages'), 'i18n_supported_langs' , variable_get('i18n_supported_langs', 'locale'),
97 array(
98 'locale' => t('Defined by the locale module'),
99 'i18n' => t('Defined in the configuration file (%config_languages)', array('%config_languages' => $config_languages))
100 ), t('Where to get the list of supported languages from' ));
101 $output .= form_radios(t('Browser language detection'), 'i18n_browser', variable_get('i18n_browser', 0), array(t('Disabled'), t('Enabled' )));
102 $output .= form_select(t('Front page'), 'i18n_frontpage', variable_get('i18n_frontpage', 0), array(t('Default'), t('Language dependent')), t(" If 'language dependent' is selected, default front page will be prepended with language code, i.e. 'en/node'"));
103 /*
104 $output .= form_textfield(t('Language icons html tag'), 'i18n_flags', variable_get('i18n_flags', '<img class="i18n-flag" src="modules/i18n/flags/*.png" width="16" height="12" alt="Language Flag" />'), 70, 180,
105 t('HTML tag for flags. Asterisk \'*\' is a placeholder for language code. It should be something like &lt;img class="i18n-flag" src="modules/i18n/flags/*.png" width="16" height="12"/&gt'));
106 */
107 $output .= form_textfield(t('Language icons path'), 'i18n_flags_path', variable_get('i18n_flags_path', 'modules/i18n/flags/*.png'), 70, 180,
108 t('Path for language icons, relative to Drupal installation. \'*\' is a placeholder for language code.'));
109 $output .= form_textfield(t('Language icons sixe'), 'i18n_flags_size', variable_get('i18n_flags_size', '16x12'), 10, 10,
110 t('Image size for language icons, in the form "width x height".'));
111
112 $output .= t('<h2>Multilingual content</h2>' );
113 foreach (node_list() as $node) {
114 $subform.=form_checkbox(t($node), 'i18n_node_'.$node, 1, variable_get('i18n_node_'.$node, 0));
115 }
116 $output .= form_group(t('Nodes' ), $subform, t('Select node types to be translated.' ));
117
118 $output .= t('<h2>Advanced Features</h2>' );
119 $output .= t('<p>These are intended only for advanced users. Some changes to the database are required. Please, do read the INSTALL.txt and README.txt files before enabling these options</p>' );
120
121 // Advanced features
122 // Language dependent tables
123 if (is_array($db_prefix_i18n)) {
124 $multi=true;
125 $text = '<strong>'.t('Current language dependent tables are: '). implode(', ', array_keys($db_prefix_i18n)).'</strong>' ;
126 } else {
127 $text = t("Check the module's SETUP.txt file.");
128 }
129 $output .= form_radios(t('Language dependent tables'), 'i18n_multi', variable_get('i18n_multi', 0), array(t('Disabled'), t('Enabled')), t('If enabled, different tables for each language will be used. They must be defined in the configuration file.') . ' ' . $text);
130
131 return $output;
132 }
133
134 /**
135 * i18n api
136 */
137
138 /**
139 * Get list of supported languages
140 */
141 function i18n_supported_languages() {
142 global $i18n_languages;
143 static $languages;
144 if ($languages) {
145 return $languages;
146 }
147 elseif (variable_get('i18n_supported_langs', 'locale') == 'locale') {
148 $languages = _i18n_locale_supported_languages();
149 return $languages;
150 }
151 elseif (is_array($i18n_languages)) {
152 return $languages = $i18n_languages;
153 }
154 else {
155 return array();
156 }
157 }
158
159 /**
160 * Returns default language
161 */
162 function i18n_default_language(){
163 return key(i18n_supported_languages());
164 }
165
166 // Get language from browser settings, but only if it is in the $i18n_languages array
167 function i18n_get_browser_lang() {
168 $languages = i18n_supported_languages();
169 $accept=explode(',',array_shift( explode(";",$_SERVER["HTTP_ACCEPT_LANGUAGE"])));
170 foreach ($accept as $lang) {
171 $lang=substr($lang,0,2);
172 if ( !empty($lang) && array_key_exists($lang,$languages)) {
173 return $lang;
174 }
175 }
176 }
177
178 /**
179 * Get language code from path.
180 *
181 * @param $path
182 * @param $trim true to remove language code from $path
183 */
184 function i18n_get_lang_prefix(&$path, $trim = false) {
185 $maybelang = array_shift(explode('/',$path));
186 $languages = i18n_supported_languages();
187 if(array_key_exists($maybelang, $languages)){
188 if($trim) {
189 $path = trim(substr($path, strlen($maybelang)),'/');
190 }
191 return $maybelang;
192 }
193 /*
194 if (preg_match("/^\w\w($|\/.*)/", $path)) {
195 return substr($path, 0, 2);
196 }
197 */
198 }
199
200 /**
201 * Language dependent front page
202 */
203 function i18n_frontpage() {
204 $path = _i18n_get_lang().'/'.variable_get('site_frontpage','node');
205 return i18n_get_normal_path($path);
206 }
207
208 /**
209 * This function is similar to drupal_get_normal_path, but language-aware
210 * Also removes language from path
211 */
212 function i18n_get_normal_path($path) {
213 // First, check alias with lang, then without
214 if ($path != ($alias = drupal_lookup_path('alias', $path))) {
215 return $alias;
216 } elseif(i18n_get_lang_prefix($path, TRUE)){
217 $alias = drupal_lookup_path('alias', $path);
218 if( $alias && $path != $alias) {
219 return $alias;
220 }
221 }
222 // We only get here when no alias is defined, with or without lang
223 return $path;
224 }
225
226 /**
227 * Gets language, checking in order:
228 *
229 * 1. Path language
230 * 2. User language
231 * 3. Browser language
232 * 4. Default language
233 */
234
235 function _i18n_get_lang() {
236 global $user, $i18n_langpath;
237 static $i18n_lang;
238
239 //see if the language is already set.
240 if ($i18n_lang) {
241 return $i18n_lang;
242 }
243
244 $languages = i18n_supported_languages();
245
246 if ($i18n_langpath && array_key_exists($i18n_langpath,$languages)) {
247 $i18n_lang = $i18n_langpath;
248 }
249 elseif ($user->uid && $user->language && array_key_exists($user->language,$languages)) {
250 $i18n_lang = $user->language;
251 }
252 elseif (variable_get("i18n_browser",0) && $lang=i18n_get_browser_lang()) {
253 $i18n_lang=$lang;
254 }
255 else {
256 $i18n_lang=key($languages);
257 }
258
259 return $i18n_lang;
260 }
261
262 /**
263 * Check whether we are in bootstrap mode
264 */
265 function _i18n_is_bootstrap(){
266 return !function_exists('drupal_get_headers');
267 }
268
269 /**
270 * Sets db_prefix to given language
271 */
272 function _i18n_set_db_prefix($lang) {
273 global $db_prefix, $db_prefix_i18n;
274 if (is_array($db_prefix_i18n)) {
275 $db_prefix = array_merge($db_prefix, str_replace('**', $lang, $db_prefix_i18n));
276 }
277 }
278
279 /**
280 * To get the original path.
281 * Cannot use $_GET["q"] cause it may have been already changed
282 */
283 function _i18n_get_original_path() {
284 return isset($_REQUEST["q"]) ? trim($_REQUEST["q"],"/") : '';
285 }
286
287
288 /**
289 * Returns list of enabled languages from locale module
290 *
291 * * Some code borrowed from locale module
292 */
293 function _i18n_locale_supported_languages() {
294 $enabled = array();
295 $result = db_query('SELECT locale, name FROM {locales_meta} WHERE enabled = 1 ORDER BY isdefault DESC, name ASC');
296 while ($row = db_fetch_object($result)) {
297 $enabled[$row->locale] = $row->name;
298 }
299 return $enabled;
300 }
301
302 /**
303 * Emulates drupal_goto, it may not be loaded yet
304 */
305 function _i18n_goto($lang){
306 if(!function_exists('drupal_goto')){
307 require_once './includes/common.inc';
308 }
309 drupal_goto($lang);
310 }
311
312 ?>