locale.install

  1. 7.x drupal-7.x/modules/locale/locale.install
  2. 6.x drupal-6.x/modules/locale/locale.install

File

drupal-6.x/modules/locale/locale.install
View source
  1. <?php
  2. /**
  3. * Implementation of hook_install().
  4. */
  5. function locale_install() {
  6. // locales_source.source and locales_target.target are not used as binary
  7. // fields; non-MySQL database servers need to ensure the field type is text
  8. // and that LIKE produces a case-sensitive comparison.
  9. // Create tables.
  10. drupal_install_schema('locale');
  11. db_query("INSERT INTO {languages} (language, name, native, direction, enabled, weight, javascript) VALUES ('en', 'English', 'English', '0', '1', '0', '')");
  12. }
  13. /**
  14. * @addtogroup updates-5.x-to-6.x
  15. * @{
  16. */
  17. /**
  18. * {locales_meta} table became {languages}.
  19. */
  20. function locale_update_6000() {
  21. $ret = array();
  22. $schema['languages'] = array(
  23. 'fields' => array(
  24. 'language' => array(
  25. 'type' => 'varchar',
  26. 'length' => 12,
  27. 'not null' => TRUE,
  28. 'default' => '',
  29. ),
  30. 'name' => array(
  31. 'type' => 'varchar',
  32. 'length' => 64,
  33. 'not null' => TRUE,
  34. 'default' => '',
  35. ),
  36. 'native' => array(
  37. 'type' => 'varchar',
  38. 'length' => 64,
  39. 'not null' => TRUE,
  40. 'default' => '',
  41. ),
  42. 'direction' => array(
  43. 'type' => 'int',
  44. 'not null' => TRUE,
  45. 'default' => 0,
  46. ),
  47. 'enabled' => array(
  48. 'type' => 'int',
  49. 'not null' => TRUE,
  50. 'default' => 0,
  51. ),
  52. 'plurals' => array(
  53. 'type' => 'int',
  54. 'not null' => TRUE,
  55. 'default' => 0,
  56. ),
  57. 'formula' => array(
  58. 'type' => 'varchar',
  59. 'length' => 128,
  60. 'not null' => TRUE,
  61. 'default' => '',
  62. ),
  63. 'domain' => array(
  64. 'type' => 'varchar',
  65. 'length' => 128,
  66. 'not null' => TRUE,
  67. 'default' => '',
  68. ),
  69. 'prefix' => array(
  70. 'type' => 'varchar',
  71. 'length' => 128,
  72. 'not null' => TRUE,
  73. 'default' => '',
  74. ),
  75. 'weight' => array(
  76. 'type' => 'int',
  77. 'not null' => TRUE,
  78. 'default' => 0,
  79. ),
  80. 'javascript' => array( //Adds a column to store the filename of the JavaScript translation file.
  81. 'type' => 'varchar',
  82. 'length' => 32,
  83. 'not null' => TRUE,
  84. 'default' => '',
  85. ),
  86. ),
  87. 'primary key' => array('language'),
  88. 'indexes' => array(
  89. 'list' => array('weight', 'name'),
  90. ),
  91. );
  92. db_create_table($ret, 'languages', $schema['languages']);
  93. // Save the languages
  94. $ret[] = update_sql("INSERT INTO {languages} (language, name, native, direction, enabled, plurals, formula, domain, prefix, weight) SELECT locale, name, name, 0, enabled, plurals, formula, '', locale, 0 FROM {locales_meta}");
  95. // Save the language count in the variable table
  96. $count = db_result(db_query('SELECT COUNT(*) FROM {languages} WHERE enabled = 1'));
  97. variable_set('language_count', $count);
  98. // Save the default language in the variable table
  99. $default = db_fetch_object(db_query('SELECT * FROM {locales_meta} WHERE isdefault = 1'));
  100. variable_set('language_default', (object) array('language' => $default->locale, 'name' => $default->name, 'native' => '', 'direction' => 0, 'enabled' => 1, 'plurals' => $default->plurals, 'formula' => $default->formula, 'domain' => '', 'prefix' => $default->locale, 'weight' => 0));
  101. $ret[] = update_sql("DROP TABLE {locales_meta}");
  102. return $ret;
  103. }
  104. /**
  105. * Change locale column to language. The language column is added by
  106. * update_fix_d6_requirements() in update.php to avoid a large number
  107. * of error messages from update.php. All we need to do here is copy
  108. * locale to language and then drop locale.
  109. */
  110. function locale_update_6001() {
  111. $ret = array();
  112. $ret[] = update_sql('UPDATE {locales_target} SET language = locale');
  113. db_drop_field($ret, 'locales_target', 'locale');
  114. return $ret;
  115. }
  116. /**
  117. * Remove empty translations, we don't need these anymore.
  118. */
  119. function locale_update_6002() {
  120. $ret = array();
  121. $ret[] = update_sql("DELETE FROM {locales_target} WHERE translation = ''");
  122. return $ret;
  123. }
  124. /**
  125. * Prune strings with no translations (will be automatically re-registered if still in use)
  126. */
  127. function locale_update_6003() {
  128. $ret = array();
  129. $ret[] = update_sql("DELETE FROM {locales_source} WHERE lid NOT IN (SELECT lid FROM {locales_target})");
  130. return $ret;
  131. }
  132. /**
  133. * Fix remaining inconsistent indexes.
  134. */
  135. function locale_update_6004() {
  136. $ret = array();
  137. db_add_index($ret, 'locales_target', 'language', array('language'));
  138. switch ($GLOBALS['db_type']) {
  139. case 'pgsql':
  140. db_drop_index($ret, 'locales_source', 'source');
  141. db_add_index($ret, 'locales_source', 'source', array(array('source', 30)));
  142. break;
  143. }
  144. return $ret;
  145. }
  146. /**
  147. * Change language setting variable of content types.
  148. *
  149. * Use language_content_type_<content_type> instead of language_<content_type>
  150. * so content types such as 'default', 'count' or 'negotiation' will not
  151. * interfere with language variables.
  152. */
  153. function locale_update_6005() {
  154. foreach (node_get_types() as $type => $content_type) {
  155. // Default to NULL, so we can skip dealing with non-existent settings.
  156. $setting = variable_get('language_'. $type, NULL);
  157. if ($type == 'default' && is_numeric($setting)) {
  158. // language_default was overwritten with the content type setting,
  159. // so reset the default language and save the content type setting.
  160. variable_set('language_content_type_default', $setting);
  161. variable_del('language_default');
  162. drupal_set_message('The default language setting has been reset to its default value. Check the '. l('language configuration page', 'admin/settings/language') .' to configure it correctly.');
  163. }
  164. elseif ($type == 'negotiation') {
  165. // language_content_type_negotiation is an integer either if it is
  166. // the negotiation setting or the content type setting.
  167. // The language_negotiation setting is not reset, but
  168. // the user is alerted that this setting possibly was overwritten
  169. variable_set('language_content_type_negotiation', $setting);
  170. drupal_set_message('The language negotiation setting was possibly overwritten by a content type of the same name. Check the '. l('language configuration page', 'admin/settings/language/configure') .' and the '. l('<em>'. $content_type->name ."</em> content type's multilingual support settings", 'admin/content/types/negotiation', array('html' => TRUE)) .' to configure them correctly.');
  171. }
  172. elseif (!is_null($setting)) {
  173. // Change the language setting variable for any other content type.
  174. // Do not worry about language_count, it will be updated below.
  175. variable_set('language_content_type_'. $type, $setting);
  176. variable_del('language_'. $type);
  177. }
  178. }
  179. // Update language count variable that might be overwritten.
  180. $count = db_result(db_query('SELECT COUNT(*) FROM {languages} WHERE enabled = 1'));
  181. variable_set('language_count', $count);
  182. return array();
  183. }
  184. /**
  185. * Neutralize unsafe language names in the database.
  186. */
  187. function locale_update_6006() {
  188. $ret = array();
  189. $matches = db_result(db_query("SELECT 1 FROM {languages} WHERE native LIKE '%<%' OR native LIKE '%>%' OR name LIKE '%<%' OR name LIKE '%>%'"));
  190. if ($matches) {
  191. $ret[] = update_sql("UPDATE {languages} SET name = REPLACE(name, '<', ''), native = REPLACE(native, '<', '')");
  192. $ret[] = update_sql("UPDATE {languages} SET name = REPLACE(name, '>', ''), native = REPLACE(native, '>', '')");
  193. drupal_set_message('The language name in English and the native language name values of all the existing custom languages of your site have been sanitized for security purposes. Visit the <a href="'. url('admin/settings/language') .'">Languages</a> page to check these and fix them if necessary.', 'warning');
  194. }
  195. // Check if some langcode values contain potentially dangerous characters and
  196. // warn the user if so. These are not fixed since they are referenced in other
  197. // tables (e.g. {node}).
  198. if (db_result(db_query("SELECT 1 FROM {languages} WHERE language LIKE '%<%' OR language LIKE '%>%' OR language LIKE '%\"%' OR language LIKE '%\\\\\%'"))) {
  199. drupal_set_message('Some of your custom language code values contain invalid characters. You should examine the <a href="'. url('admin/settings/language') .'">Languages</a> page. These must be fixed manually.', 'error');
  200. }
  201. return $ret;
  202. }
  203. /**
  204. * @} End of "addtogroup updates-5.x-to-6.x".
  205. */
  206. /**
  207. * @addtogroup updates-6.x-extra
  208. * @{
  209. */
  210. /**
  211. * Fix Drupal.formatPlural().
  212. */
  213. function locale_update_6007() {
  214. drupal_load('module', 'locale');
  215. locale_inc_callback('_locale_invalidate_js');
  216. return array();
  217. }
  218. /**
  219. * @} End of "addtogroup updates-6.x-extra".
  220. * The next series of updates should start at 7000.
  221. */
  222. /**
  223. * Implementation of hook_uninstall().
  224. */
  225. function locale_uninstall() {
  226. // Delete all JavaScript translation files
  227. $files = db_query('SELECT javascript FROM {languages}');
  228. while ($file = db_fetch_object($files)) {
  229. if (!empty($file)) {
  230. file_delete(file_create_path($file->javascript));
  231. }
  232. }
  233. // Clear variables.
  234. variable_del('language_default');
  235. variable_del('language_count');
  236. variable_del('language_content_type_default');
  237. variable_del('language_content_type_negotiation');
  238. variable_del('locale_cache_strings');
  239. variable_del('locale_js_directory');
  240. variable_del('javascript_parsed');
  241. variable_del('language_negotiation');
  242. foreach (node_get_types() as $type => $content_type) {
  243. variable_del("language_content_type_$type");
  244. }
  245. // Switch back to English: with a $language->language value different from
  246. // 'en' successive calls of t() might result in calling locale(), which in
  247. // turn might try to query the unexisting {locales_source} and
  248. // {locales_target} tables.
  249. drupal_init_language();
  250. // Remove tables.
  251. drupal_uninstall_schema('locale');
  252. }
  253. /**
  254. * Implementation of hook_schema().
  255. */
  256. function locale_schema() {
  257. $schema['languages'] = array(
  258. 'description' => 'List of all available languages in the system.',
  259. 'fields' => array(
  260. 'language' => array(
  261. 'type' => 'varchar',
  262. 'length' => 12,
  263. 'not null' => TRUE,
  264. 'default' => '',
  265. 'description' => "Language code, e.g. 'de' or 'en-US'.",
  266. ),
  267. 'name' => array(
  268. 'type' => 'varchar',
  269. 'length' => 64,
  270. 'not null' => TRUE,
  271. 'default' => '',
  272. 'description' => 'Language name in English.',
  273. ),
  274. 'native' => array(
  275. 'type' => 'varchar',
  276. 'length' => 64,
  277. 'not null' => TRUE,
  278. 'default' => '',
  279. 'description' => 'Native language name.',
  280. ),
  281. 'direction' => array(
  282. 'type' => 'int',
  283. 'not null' => TRUE,
  284. 'default' => 0,
  285. 'description' => 'Direction of language (Left-to-Right = 0, Right-to-Left = 1).',
  286. ),
  287. 'enabled' => array(
  288. 'type' => 'int',
  289. 'not null' => TRUE,
  290. 'default' => 0,
  291. 'description' => 'Enabled flag (1 = Enabled, 0 = Disabled).',
  292. ),
  293. 'plurals' => array(
  294. 'type' => 'int',
  295. 'not null' => TRUE,
  296. 'default' => 0,
  297. 'description' => 'Number of plural indexes in this language.',
  298. ),
  299. 'formula' => array(
  300. 'type' => 'varchar',
  301. 'length' => 128,
  302. 'not null' => TRUE,
  303. 'default' => '',
  304. 'description' => 'Plural formula in PHP code to evaluate to get plural indexes.',
  305. ),
  306. 'domain' => array(
  307. 'type' => 'varchar',
  308. 'length' => 128,
  309. 'not null' => TRUE,
  310. 'default' => '',
  311. 'description' => 'Domain to use for this language.',
  312. ),
  313. 'prefix' => array(
  314. 'type' => 'varchar',
  315. 'length' => 128,
  316. 'not null' => TRUE,
  317. 'default' => '',
  318. 'description' => 'Path prefix to use for this language.',
  319. ),
  320. 'weight' => array(
  321. 'type' => 'int',
  322. 'not null' => TRUE,
  323. 'default' => 0,
  324. 'description' => 'Weight, used in lists of languages.',
  325. ),
  326. 'javascript' => array(
  327. 'type' => 'varchar',
  328. 'length' => 32,
  329. 'not null' => TRUE,
  330. 'default' => '',
  331. 'description' => 'Location of JavaScript translation file.',
  332. ),
  333. ),
  334. 'primary key' => array('language'),
  335. 'indexes' => array(
  336. 'list' => array('weight', 'name'),
  337. ),
  338. );
  339. $schema['locales_source'] = array(
  340. 'description' => 'List of English source strings.',
  341. 'fields' => array(
  342. 'lid' => array(
  343. 'type' => 'serial',
  344. 'not null' => TRUE,
  345. 'description' => 'Unique identifier of this string.',
  346. ),
  347. 'location' => array(
  348. 'type' => 'varchar',
  349. 'length' => 255,
  350. 'not null' => TRUE,
  351. 'default' => '',
  352. 'description' => 'Drupal path in case of online discovered translations or file path in case of imported strings.',
  353. ),
  354. 'textgroup' => array(
  355. 'type' => 'varchar',
  356. 'length' => 255,
  357. 'not null' => TRUE,
  358. 'default' => 'default',
  359. 'description' => 'A module defined group of translations, see hook_locale().',
  360. ),
  361. 'source' => array(
  362. 'type' => 'text',
  363. 'mysql_type' => 'blob',
  364. 'not null' => TRUE,
  365. 'description' => 'The original string in English.',
  366. ),
  367. 'version' => array(
  368. 'type' => 'varchar',
  369. 'length' => 20,
  370. 'not null' => TRUE,
  371. 'default' => 'none',
  372. 'description' => 'Version of Drupal, where the string was last used (for locales optimization).',
  373. ),
  374. ),
  375. 'primary key' => array('lid'),
  376. 'indexes' => array(
  377. 'source' => array(array('source', 30)),
  378. ),
  379. );
  380. $schema['locales_target'] = array(
  381. 'description' => 'Stores translated versions of strings.',
  382. 'fields' => array(
  383. 'lid' => array(
  384. 'type' => 'int',
  385. 'not null' => TRUE,
  386. 'default' => 0,
  387. 'description' => 'Source string ID. References {locales_source}.lid.',
  388. ),
  389. 'translation' => array(
  390. 'type' => 'text',
  391. 'mysql_type' => 'blob',
  392. 'not null' => TRUE,
  393. 'description' => 'Translation string value in this language.',
  394. ),
  395. 'language' => array(
  396. 'type' => 'varchar',
  397. 'length' => 12,
  398. 'not null' => TRUE,
  399. 'default' => '',
  400. 'description' => 'Language code. References {languages}.language.',
  401. ),
  402. 'plid' => array(
  403. 'type' => 'int',
  404. 'not null' => TRUE, // This should be NULL for no referenced string, not zero.
  405. 'default' => 0,
  406. 'description' => 'Parent lid (lid of the previous string in the plural chain) in case of plural strings. References {locales_source}.lid.',
  407. ),
  408. 'plural' => array(
  409. 'type' => 'int',
  410. 'not null' => TRUE,
  411. 'default' => 0,
  412. 'description' => 'Plural index number in case of plural strings.',
  413. ),
  414. ),
  415. 'primary key' => array('language', 'lid', 'plural'),
  416. 'indexes' => array(
  417. 'lid' => array('lid'),
  418. 'plid' => array('plid'),
  419. 'plural' => array('plural'),
  420. ),
  421. );
  422. return $schema;
  423. }