|
1 <?php |
|
2 |
|
3 /** |
|
4 * @file |
|
5 * Install, update and uninstall functions for the locale module. |
|
6 */ |
|
7 |
|
8 /** |
|
9 * Implements hook_install(). |
|
10 */ |
|
11 function locale_install() { |
|
12 // locales_source.source and locales_target.target are not used as binary |
|
13 // fields; non-MySQL database servers need to ensure the field type is text |
|
14 // and that LIKE produces a case-sensitive comparison. |
|
15 |
|
16 db_insert('languages') |
|
17 ->fields(array( |
|
18 'language' => 'en', |
|
19 'name' => 'English', |
|
20 'native' => 'English', |
|
21 'direction' => 0, |
|
22 'enabled' => 1, |
|
23 'weight' => 0, |
|
24 'javascript' => '', |
|
25 )) |
|
26 ->execute(); |
|
27 } |
|
28 |
|
29 /** |
|
30 * @addtogroup updates-6.x-to-7.x |
|
31 * @{ |
|
32 */ |
|
33 |
|
34 /** |
|
35 * Add context field index and allow longer location. |
|
36 */ |
|
37 function locale_update_7000() { |
|
38 db_drop_index('locales_source', 'source'); |
|
39 db_add_index('locales_source', 'source_context', array(array('source', 30), 'context')); |
|
40 |
|
41 // Also drop the 'textgroup_location' index added by the i18nstrings module |
|
42 // of the i18n project, which prevents the below schema update from running. |
|
43 if (db_index_exists('locales_source', 'textgroup_location')) { |
|
44 db_drop_index('locales_source', 'textgroup_location'); |
|
45 } |
|
46 |
|
47 db_change_field('locales_source', 'location', 'location', array( |
|
48 'type' => 'text', |
|
49 'not null' => FALSE, |
|
50 'size' => 'big', |
|
51 'description' => 'Drupal path in case of online discovered translations or file path in case of imported strings.', |
|
52 )); |
|
53 } |
|
54 |
|
55 /** |
|
56 * Upgrade language negotiation settings. |
|
57 */ |
|
58 function locale_update_7001() { |
|
59 require_once DRUPAL_ROOT . '/includes/language.inc'; |
|
60 require_once DRUPAL_ROOT . '/includes/locale.inc'; |
|
61 require_once DRUPAL_ROOT . '/modules/locale/locale.module'; |
|
62 |
|
63 switch (variable_get('language_negotiation', 0)) { |
|
64 // LANGUAGE_NEGOTIATION_NONE. |
|
65 case 0: |
|
66 $negotiation = array(); |
|
67 break; |
|
68 |
|
69 // LANGUAGE_NEGOTIATION_PATH_DEFAULT. |
|
70 case 1: |
|
71 $negotiation = array(LOCALE_LANGUAGE_NEGOTIATION_URL); |
|
72 // In Drupal 6 path prefixes are shown for the default language only when |
|
73 // language negotiation is set to LANGUAGE_NEGOTIATION_PATH, while in |
|
74 // Drupal 7 path prefixes are always shown if not empty. Hence we need to |
|
75 // ensure that the default language has an empty prefix to avoid breaking |
|
76 // the site URLs with a prefix that previously was missing. |
|
77 $default = language_default(); |
|
78 $default->prefix = ''; |
|
79 variable_set('language_default', $default); |
|
80 db_update('languages') |
|
81 ->fields(array('prefix' => $default->prefix)) |
|
82 ->condition('language', $default->language) |
|
83 ->execute(); |
|
84 break; |
|
85 |
|
86 // LANGUAGE_NEGOTIATION_PATH. |
|
87 case 2: |
|
88 $negotiation = array(LOCALE_LANGUAGE_NEGOTIATION_URL, LOCALE_LANGUAGE_NEGOTIATION_USER, LOCALE_LANGUAGE_NEGOTIATION_BROWSER); |
|
89 break; |
|
90 |
|
91 // LANGUAGE_NEGOTIATION_DOMAIN. |
|
92 case 3: |
|
93 variable_set('locale_language_negotiation_url_part', LOCALE_LANGUAGE_NEGOTIATION_URL_DOMAIN); |
|
94 $negotiation = array(LOCALE_LANGUAGE_NEGOTIATION_URL); |
|
95 break; |
|
96 } |
|
97 |
|
98 // Save the new language negotiation options. |
|
99 language_negotiation_set(LANGUAGE_TYPE_INTERFACE, array_flip($negotiation)); |
|
100 language_negotiation_set(LANGUAGE_TYPE_CONTENT, array(LOCALE_LANGUAGE_NEGOTIATION_INTERFACE => 0)); |
|
101 language_negotiation_set(LANGUAGE_TYPE_URL, array(LOCALE_LANGUAGE_NEGOTIATION_URL => 0)); |
|
102 |
|
103 // Save admininstration UI settings. |
|
104 $type = LANGUAGE_TYPE_INTERFACE; |
|
105 $provider_weights = array_flip(array_keys(locale_language_negotiation_info())); |
|
106 variable_set("locale_language_providers_weight_$type", $provider_weights); |
|
107 |
|
108 // Unset the old language negotiation system variable. |
|
109 variable_del('language_negotiation'); |
|
110 |
|
111 return array(); |
|
112 } |
|
113 |
|
114 /** |
|
115 * Updates URL language negotiation by adding the URL fallback detection method. |
|
116 */ |
|
117 function locale_update_7002() { |
|
118 // language.inc may not have been included during bootstrap if there is not |
|
119 // more than one language currently enabled. |
|
120 require_once DRUPAL_ROOT . '/includes/language.inc'; |
|
121 $language_types_info = language_types_info(); |
|
122 $info = $language_types_info[LANGUAGE_TYPE_URL]; |
|
123 if (isset($info['fixed'])) { |
|
124 language_negotiation_set(LANGUAGE_TYPE_URL, array_flip($info['fixed'])); |
|
125 } |
|
126 } |
|
127 |
|
128 /** |
|
129 * @} End of "addtogroup updates-6.x-to-7.x". |
|
130 */ |
|
131 |
|
132 /** |
|
133 * @addtogroup updates-7.x-extra |
|
134 * @{ |
|
135 */ |
|
136 |
|
137 /** |
|
138 * Update "language_count" variable. |
|
139 */ |
|
140 function locale_update_7003() { |
|
141 $languages = language_list('enabled'); |
|
142 variable_set('language_count', count($languages[1])); |
|
143 } |
|
144 |
|
145 /** |
|
146 * Remove duplicates in {locales_source}. |
|
147 */ |
|
148 function locale_update_7004() { |
|
149 // Look up all duplicates. For each set of duplicates, we select the row |
|
150 // with the lowest lid as the "master" that will be preserved. |
|
151 $result_source = db_query("SELECT MIN(lid) AS lid, source, context FROM {locales_source} WHERE textgroup = 'default' GROUP BY source, context HAVING COUNT(*) > 1"); |
|
152 |
|
153 $conflict = FALSE; |
|
154 foreach ($result_source as $source) { |
|
155 // Find all rows in {locales_target} that are translations of the same |
|
156 // string (incl. context). |
|
157 $result_target = db_query("SELECT t.lid, t.language, t.plural, t.translation FROM {locales_source} s JOIN {locales_target} t ON s.lid = t.lid WHERE s.source = :source AND s.context = :context AND s.textgroup = 'default' ORDER BY lid", array( |
|
158 ':source' => $source->source, |
|
159 ':context' => $source->context, |
|
160 )); |
|
161 |
|
162 $translations = array(); |
|
163 $keep_lids = array($source->lid); |
|
164 foreach ($result_target as $target) { |
|
165 if (!isset($translations[$target->language])) { |
|
166 $translations[$target->language] = $target->translation; |
|
167 if ($target->lid != $source->lid) { |
|
168 // Move translation to the master lid. |
|
169 db_query('UPDATE {locales_target} SET lid = :new_lid WHERE lid = :old_lid', array( |
|
170 ':new_lid' => $source->lid, |
|
171 ':old_lid' => $target->lid)); |
|
172 } |
|
173 } |
|
174 elseif ($translations[$target->language] == $target->translation) { |
|
175 // Delete duplicate translation. |
|
176 db_query('DELETE FROM {locales_target} WHERE lid = :lid AND language = :language', array( |
|
177 ':lid' => $target->lid, |
|
178 ':language' => $target->language)); |
|
179 } |
|
180 else { |
|
181 // The same string is translated into several different strings in one |
|
182 // language. We do not know which is the preferred, so we keep them all. |
|
183 $keep_lids[] = $target->lid; |
|
184 $conflict = TRUE; |
|
185 } |
|
186 } |
|
187 |
|
188 // Delete rows in {locales_source} that are no longer referenced from |
|
189 // {locales_target}. |
|
190 db_delete('locales_source') |
|
191 ->condition('source', $source->source) |
|
192 ->condition('context', $source->context) |
|
193 ->condition('textgroup', 'default') |
|
194 ->condition('lid', $keep_lids, 'NOT IN') |
|
195 ->execute(); |
|
196 } |
|
197 |
|
198 if ($conflict) { |
|
199 $url = 'http://drupal.org/node/746240'; |
|
200 drupal_set_message('Your {locales_source} table contains duplicates that could not be removed automatically. See <a href="' . $url .'" target="_blank">' . $url . '</a> for more information.', 'warning'); |
|
201 } |
|
202 } |
|
203 |
|
204 /** |
|
205 * Increase {locales_languages}.formula column's length. |
|
206 */ |
|
207 function locale_update_7005() { |
|
208 db_change_field('languages', 'formula', 'formula', array( |
|
209 'type' => 'varchar', |
|
210 'length' => 255, |
|
211 'not null' => TRUE, |
|
212 'default' => '', |
|
213 'description' => 'Plural formula in PHP code to evaluate to get plural indexes.', |
|
214 )); |
|
215 } |
|
216 |
|
217 /** |
|
218 * @} End of "addtogroup updates-7.x-extra". |
|
219 */ |
|
220 |
|
221 /** |
|
222 * Implements hook_uninstall(). |
|
223 */ |
|
224 function locale_uninstall() { |
|
225 // Delete all JavaScript translation files. |
|
226 $locale_js_directory = 'public://' . variable_get('locale_js_directory', 'languages'); |
|
227 |
|
228 if (is_dir($locale_js_directory)) { |
|
229 $files = db_query('SELECT language, javascript FROM {languages}'); |
|
230 foreach ($files as $file) { |
|
231 if (!empty($file->javascript)) { |
|
232 file_unmanaged_delete($locale_js_directory . '/' . $file->language . '_' . $file->javascript . '.js'); |
|
233 } |
|
234 } |
|
235 // Delete the JavaScript translations directory if empty. |
|
236 if (!file_scan_directory($locale_js_directory, '/.*/')) { |
|
237 drupal_rmdir($locale_js_directory); |
|
238 } |
|
239 } |
|
240 |
|
241 // Clear variables. |
|
242 variable_del('language_default'); |
|
243 variable_del('language_count'); |
|
244 variable_del('language_types'); |
|
245 variable_del('locale_language_negotiation_url_part'); |
|
246 variable_del('locale_language_negotiation_session_param'); |
|
247 variable_del('language_content_type_default'); |
|
248 variable_del('language_content_type_negotiation'); |
|
249 variable_del('locale_cache_strings'); |
|
250 variable_del('locale_js_directory'); |
|
251 variable_del('javascript_parsed'); |
|
252 variable_del('locale_field_language_fallback'); |
|
253 variable_del('locale_cache_length'); |
|
254 |
|
255 foreach (language_types() as $type) { |
|
256 variable_del("language_negotiation_$type"); |
|
257 variable_del("locale_language_providers_weight_$type"); |
|
258 } |
|
259 |
|
260 foreach (node_type_get_types() as $type => $content_type) { |
|
261 $setting = variable_del("language_content_type_$type"); |
|
262 } |
|
263 |
|
264 // Switch back to English: with a $language->language value different from 'en' |
|
265 // successive calls of t() might result in calling locale(), which in turn might |
|
266 // try to query the unexisting {locales_source} and {locales_target} tables. |
|
267 drupal_language_initialize(); |
|
268 |
|
269 } |
|
270 |
|
271 /** |
|
272 * Implements hook_schema(). |
|
273 */ |
|
274 function locale_schema() { |
|
275 $schema['languages'] = array( |
|
276 'description' => 'List of all available languages in the system.', |
|
277 'fields' => array( |
|
278 'language' => array( |
|
279 'type' => 'varchar', |
|
280 'length' => 12, |
|
281 'not null' => TRUE, |
|
282 'default' => '', |
|
283 'description' => "Language code, e.g. 'de' or 'en-US'.", |
|
284 ), |
|
285 'name' => array( |
|
286 'type' => 'varchar', |
|
287 'length' => 64, |
|
288 'not null' => TRUE, |
|
289 'default' => '', |
|
290 'description' => 'Language name in English.', |
|
291 ), |
|
292 'native' => array( |
|
293 'type' => 'varchar', |
|
294 'length' => 64, |
|
295 'not null' => TRUE, |
|
296 'default' => '', |
|
297 'description' => 'Native language name.', |
|
298 ), |
|
299 'direction' => array( |
|
300 'type' => 'int', |
|
301 'not null' => TRUE, |
|
302 'default' => 0, |
|
303 'description' => 'Direction of language (Left-to-Right = 0, Right-to-Left = 1).', |
|
304 ), |
|
305 'enabled' => array( |
|
306 'type' => 'int', |
|
307 'not null' => TRUE, |
|
308 'default' => 0, |
|
309 'description' => 'Enabled flag (1 = Enabled, 0 = Disabled).', |
|
310 ), |
|
311 'plurals' => array( |
|
312 'type' => 'int', |
|
313 'not null' => TRUE, |
|
314 'default' => 0, |
|
315 'description' => 'Number of plural indexes in this language.', |
|
316 ), |
|
317 'formula' => array( |
|
318 'type' => 'varchar', |
|
319 'length' => 255, |
|
320 'not null' => TRUE, |
|
321 'default' => '', |
|
322 'description' => 'Plural formula in PHP code to evaluate to get plural indexes.', |
|
323 ), |
|
324 'domain' => array( |
|
325 'type' => 'varchar', |
|
326 'length' => 128, |
|
327 'not null' => TRUE, |
|
328 'default' => '', |
|
329 'description' => 'Domain to use for this language.', |
|
330 ), |
|
331 'prefix' => array( |
|
332 'type' => 'varchar', |
|
333 'length' => 128, |
|
334 'not null' => TRUE, |
|
335 'default' => '', |
|
336 'description' => 'Path prefix to use for this language.', |
|
337 ), |
|
338 'weight' => array( |
|
339 'type' => 'int', |
|
340 'not null' => TRUE, |
|
341 'default' => 0, |
|
342 'description' => 'Weight, used in lists of languages.', |
|
343 ), |
|
344 'javascript' => array( |
|
345 'type' => 'varchar', |
|
346 'length' => 64, |
|
347 'not null' => TRUE, |
|
348 'default' => '', |
|
349 'description' => 'Location of JavaScript translation file.', |
|
350 ), |
|
351 ), |
|
352 'primary key' => array('language'), |
|
353 'indexes' => array( |
|
354 'list' => array('weight', 'name'), |
|
355 ), |
|
356 ); |
|
357 |
|
358 $schema['locales_source'] = array( |
|
359 'description' => 'List of English source strings.', |
|
360 'fields' => array( |
|
361 'lid' => array( |
|
362 'type' => 'serial', |
|
363 'not null' => TRUE, |
|
364 'description' => 'Unique identifier of this string.', |
|
365 ), |
|
366 'location' => array( |
|
367 'type' => 'text', |
|
368 'not null' => FALSE, |
|
369 'size' => 'big', |
|
370 'description' => 'Drupal path in case of online discovered translations or file path in case of imported strings.', |
|
371 ), |
|
372 'textgroup' => array( |
|
373 'type' => 'varchar', |
|
374 'length' => 255, |
|
375 'not null' => TRUE, |
|
376 'default' => 'default', |
|
377 'description' => 'A module defined group of translations, see hook_locale().', |
|
378 ), |
|
379 'source' => array( |
|
380 'type' => 'text', |
|
381 'mysql_type' => 'blob', |
|
382 'not null' => TRUE, |
|
383 'description' => 'The original string in English.', |
|
384 ), |
|
385 'context' => array( |
|
386 'type' => 'varchar', |
|
387 'length' => 255, |
|
388 'not null' => TRUE, |
|
389 'default' => '', |
|
390 'description' => 'The context this string applies to.', |
|
391 ), |
|
392 'version' => array( |
|
393 'type' => 'varchar', |
|
394 'length' => 20, |
|
395 'not null' => TRUE, |
|
396 'default' => 'none', |
|
397 'description' => 'Version of Drupal, where the string was last used (for locales optimization).', |
|
398 ), |
|
399 ), |
|
400 'primary key' => array('lid'), |
|
401 'indexes' => array( |
|
402 'source_context' => array(array('source', 30), 'context'), |
|
403 ), |
|
404 ); |
|
405 |
|
406 $schema['locales_target'] = array( |
|
407 'description' => 'Stores translated versions of strings.', |
|
408 'fields' => array( |
|
409 'lid' => array( |
|
410 'type' => 'int', |
|
411 'not null' => TRUE, |
|
412 'default' => 0, |
|
413 'description' => 'Source string ID. References {locales_source}.lid.', |
|
414 ), |
|
415 'translation' => array( |
|
416 'type' => 'text', |
|
417 'mysql_type' => 'blob', |
|
418 'not null' => TRUE, |
|
419 'description' => 'Translation string value in this language.', |
|
420 ), |
|
421 'language' => array( |
|
422 'type' => 'varchar', |
|
423 'length' => 12, |
|
424 'not null' => TRUE, |
|
425 'default' => '', |
|
426 'description' => 'Language code. References {languages}.language.', |
|
427 ), |
|
428 'plid' => array( |
|
429 'type' => 'int', |
|
430 'not null' => TRUE, // This should be NULL for no referenced string, not zero. |
|
431 'default' => 0, |
|
432 'description' => 'Parent lid (lid of the previous string in the plural chain) in case of plural strings. References {locales_source}.lid.', |
|
433 ), |
|
434 'plural' => array( |
|
435 'type' => 'int', |
|
436 'not null' => TRUE, |
|
437 'default' => 0, |
|
438 'description' => 'Plural index number in case of plural strings.', |
|
439 ), |
|
440 ), |
|
441 'primary key' => array('language', 'lid', 'plural'), |
|
442 'foreign keys' => array( |
|
443 'locales_source' => array( |
|
444 'table' => 'locales_source', |
|
445 'columns' => array('lid' => 'lid'), |
|
446 ), |
|
447 ), |
|
448 'indexes' => array( |
|
449 'lid' => array('lid'), |
|
450 'plid' => array('plid'), |
|
451 'plural' => array('plural'), |
|
452 ), |
|
453 ); |
|
454 |
|
455 return $schema; |
|
456 } |
|
457 |