00001 <?php
00002
00003
00012 define('LOCALE_JS_STRING', '(?:(?:\'(?:\\\\\'|[^\'])*\'|"(?:\\\\"|[^"])*")(?:\s*\+\s*)?)+');
00013
00018 define('LOCALE_IMPORT_OVERWRITE', 0);
00019
00024 define('LOCALE_IMPORT_KEEP', 1);
00025
00034 function locale_languages_overview_form() {
00035 $languages = language_list('language', TRUE);
00036
00037 $options = array();
00038 $form['weight'] = array('#tree' => TRUE);
00039 foreach ($languages as $langcode => $language) {
00040
00041 $options[$langcode] = '';
00042 if ($language->enabled) {
00043 $enabled[] = $langcode;
00044 }
00045 $form['weight'][$langcode] = array(
00046 '#type' => 'weight',
00047 '#default_value' => $language->weight
00048 );
00049 $form['name'][$langcode] = array('#value' => check_plain($language->name));
00050 $form['native'][$langcode] = array('#value' => check_plain($language->native));
00051 $form['direction'][$langcode] = array('#value' => ($language->direction == LANGUAGE_RTL ? t('Right to left') : t('Left to right')));
00052 }
00053 $form['enabled'] = array('#type' => 'checkboxes',
00054 '#options' => $options,
00055 '#default_value' => $enabled,
00056 );
00057 $form['site_default'] = array('#type' => 'radios',
00058 '#options' => $options,
00059 '#default_value' => language_default('language'),
00060 );
00061 $form['submit'] = array('#type' => 'submit', '#value' => t('Save configuration'));
00062 $form['#theme'] = 'locale_languages_overview_form';
00063
00064 return $form;
00065 }
00066
00072 function theme_locale_languages_overview_form($form) {
00073 $default = language_default();
00074 foreach ($form['name'] as $key => $element) {
00075
00076 if (is_array($element) && element_child($key)) {
00077
00078 if ($key == $default->language) {
00079 $form['enabled'][$key]['#attributes']['disabled'] = 'disabled';
00080 }
00081 $rows[] = array(
00082 array('data' => drupal_render($form['enabled'][$key]), 'align' => 'center'),
00083 check_plain($key),
00084 '<strong>' . drupal_render($form['name'][$key]) . '</strong>',
00085 drupal_render($form['native'][$key]),
00086 drupal_render($form['direction'][$key]),
00087 drupal_render($form['site_default'][$key]),
00088 drupal_render($form['weight'][$key]),
00089 l(t('edit'), 'admin/settings/language/edit/' . $key) . (($key != 'en' && $key != $default->language) ? ' ' . l(t('delete'), 'admin/settings/language/delete/' . $key) : '')
00090 );
00091 }
00092 }
00093 $header = array(array('data' => t('Enabled')), array('data' => t('Code')), array('data' => t('English name')), array('data' => t('Native name')), array('data' => t('Direction')), array('data' => t('Default')), array('data' => t('Weight')), array('data' => t('Operations')));
00094 $output = theme('table', $header, $rows);
00095 $output .= drupal_render($form);
00096
00097 return $output;
00098 }
00099
00103 function locale_languages_overview_form_submit($form, &$form_state) {
00104 $languages = language_list();
00105 $default = language_default();
00106 $enabled_count = 0;
00107 foreach ($languages as $langcode => $language) {
00108 if ($form_state['values']['site_default'] == $langcode || $default->language == $langcode) {
00109
00110
00111
00112 $form_state['values']['enabled'][$langcode] = 1;
00113 }
00114 if ($form_state['values']['enabled'][$langcode]) {
00115 $enabled_count++;
00116 $language->enabled = 1;
00117 }
00118 else {
00119 $language->enabled = 0;
00120 }
00121 $language->weight = $form_state['values']['weight'][$langcode];
00122 db_query("UPDATE {languages} SET enabled = %d, weight = %d WHERE language = '%s'", $language->enabled, $language->weight, $langcode);
00123 $languages[$langcode] = $language;
00124 }
00125 drupal_set_message(t('Configuration saved.'));
00126 variable_set('language_default', $languages[$form_state['values']['site_default']]);
00127 variable_set('language_count', $enabled_count);
00128
00129
00130 cache_clear_all('*', 'cache_page', TRUE);
00131
00132 $form_state['redirect'] = 'admin/settings/language';
00133 return;
00134 }
00147 function locale_languages_add_screen() {
00148 $output = drupal_get_form('locale_languages_predefined_form');
00149 $output .= drupal_get_form('locale_languages_custom_form');
00150 return $output;
00151 }
00152
00156 function locale_languages_predefined_form() {
00157 $predefined = _locale_prepare_predefined_list();
00158 $form = array();
00159 $form['language list'] = array('#type' => 'fieldset',
00160 '#title' => t('Predefined language'),
00161 '#collapsible' => TRUE,
00162 );
00163 $form['language list']['langcode'] = array('#type' => 'select',
00164 '#title' => t('Language name'),
00165 '#default_value' => key($predefined),
00166 '#options' => $predefined,
00167 '#description' => t('Select the desired language and click the <em>Add language</em> button. (Use the <em>Custom language</em> options if your desired language does not appear in this list.)'),
00168 );
00169 $form['language list']['submit'] = array('#type' => 'submit', '#value' => t('Add language'));
00170 return $form;
00171 }
00172
00176 function locale_languages_custom_form() {
00177 $form = array();
00178 $form['custom language'] = array('#type' => 'fieldset',
00179 '#title' => t('Custom language'),
00180 '#collapsible' => TRUE,
00181 '#collapsed' => TRUE,
00182 );
00183 _locale_languages_common_controls($form['custom language']);
00184 $form['custom language']['submit'] = array(
00185 '#type' => 'submit',
00186 '#value' => t('Add custom language')
00187 );
00188
00189 $form['#submit'][] = 'locale_languages_predefined_form_submit';
00190 $form['#validate'][] = 'locale_languages_predefined_form_validate';
00191 return $form;
00192 }
00193
00200 function locale_languages_edit_form(&$form_state, $langcode) {
00201 if ($language = db_fetch_object(db_query("SELECT * FROM {languages} WHERE language = '%s'", $langcode))) {
00202 $form = array();
00203 _locale_languages_common_controls($form, $language);
00204 $form['submit'] = array(
00205 '#type' => 'submit',
00206 '#value' => t('Save language')
00207 );
00208 $form['#submit'][] = 'locale_languages_edit_form_submit';
00209 $form['#validate'][] = 'locale_languages_edit_form_validate';
00210 return $form;
00211 }
00212 else {
00213 drupal_not_found();
00214 }
00215 }
00216
00225 function _locale_languages_common_controls(&$form, $language = NULL) {
00226 if (!is_object($language)) {
00227 $language = new stdClass();
00228 }
00229 if (isset($language->language)) {
00230 $form['langcode_view'] = array(
00231 '#type' => 'item',
00232 '#title' => t('Language code'),
00233 '#value' => $language->language
00234 );
00235 $form['langcode'] = array(
00236 '#type' => 'value',
00237 '#value' => $language->language
00238 );
00239 }
00240 else {
00241 $form['langcode'] = array('#type' => 'textfield',
00242 '#title' => t('Language code'),
00243 '#size' => 12,
00244 '#maxlength' => 60,
00245 '#required' => TRUE,
00246 '#default_value' => @$language->language,
00247 '#disabled' => (isset($language->language)),
00248 '#description' => t('<a href="@rfc4646">RFC 4646</a> compliant language identifier. Language codes typically use a country code, and optionally, a script or regional variant name. <em>Examples: "en", "en-US" and "zh-Hant".</em>', array('@rfc4646' => 'http://www.ietf.org/rfc/rfc4646.txt')),
00249 );
00250 }
00251 $form['name'] = array('#type' => 'textfield',
00252 '#title' => t('Language name in English'),
00253 '#maxlength' => 64,
00254 '#default_value' => @$language->name,
00255 '#required' => TRUE,
00256 '#description' => t('Name of the language in English. Will be available for translation in all languages.'),
00257 );
00258 $form['native'] = array('#type' => 'textfield',
00259 '#title' => t('Native language name'),
00260 '#maxlength' => 64,
00261 '#default_value' => @$language->native,
00262 '#required' => TRUE,
00263 '#description' => t('Name of the language in the language being added.'),
00264 );
00265 $form['prefix'] = array('#type' => 'textfield',
00266 '#title' => t('Path prefix'),
00267 '#maxlength' => 64,
00268 '#default_value' => @$language->prefix,
00269 '#description' => t('Language code or other custom string for pattern matching within the path. With language negotiation set to <em>Path prefix only</em> or <em>Path prefix with language fallback</em>, this site is presented in this language when the Path prefix value matches an element in the path. For the default language, this value may be left blank. <strong>Modifying this value will break existing URLs and should be used with caution in a production environment.</strong> <em>Example: Specifying "deutsch" as the path prefix for German results in URLs in the form "www.example.com/deutsch/node".</em>')
00270 );
00271 $form['domain'] = array('#type' => 'textfield',
00272 '#title' => t('Language domain'),
00273 '#maxlength' => 64,
00274 '#default_value' => @$language->domain,
00275 '#description' => t('Language-specific URL, with protocol. With language negotiation set to <em>Domain name only</em>, the site is presented in this language when the URL accessing the site references this domain. For the default language, this value may be left blank. <strong>This value must include a protocol as part of the string.</strong> <em>Example: Specifying "http://example.de" or "http://de.example.com" as language domains for German results in URLs in the forms "http://example.de/node" and "http://de.example.com/node", respectively.</em>'),
00276 );
00277 $form['direction'] = array('#type' => 'radios',
00278 '#title' => t('Direction'),
00279 '#required' => TRUE,
00280 '#description' => t('Direction that text in this language is presented.'),
00281 '#default_value' => @$language->direction,
00282 '#options' => array(LANGUAGE_LTR => t('Left to right'), LANGUAGE_RTL => t('Right to left'))
00283 );
00284 return $form;
00285 }
00286
00290 function locale_languages_predefined_form_validate($form, &$form_state) {
00291 $langcode = $form_state['values']['langcode'];
00292
00293 if ($duplicate = db_result(db_query("SELECT COUNT(*) FROM {languages} WHERE language = '%s'", $langcode)) != 0) {
00294 form_set_error('langcode', t('The language %language (%code) already exists.', array('%language' => $form_state['values']['name'], '%code' => $langcode)));
00295 }
00296
00297 if (!isset($form_state['values']['name'])) {
00298
00299 $predefined = _locale_get_predefined_list();
00300 if (!isset($predefined[$langcode])) {
00301 form_set_error('langcode', t('Invalid language code.'));
00302 }
00303 }
00304 else {
00305
00306 locale_languages_edit_form_validate($form, $form_state);
00307 }
00308 }
00309
00313 function locale_languages_predefined_form_submit($form, &$form_state) {
00314 $langcode = $form_state['values']['langcode'];
00315 if (isset($form_state['values']['name'])) {
00316
00317 locale_add_language($langcode, $form_state['values']['name'], $form_state['values']['native'], $form_state['values']['direction'], $form_state['values']['domain'], $form_state['values']['prefix']);
00318 drupal_set_message(t('The language %language has been created and can now be used. More information is available on the <a href="@locale-help">help screen</a>.', array('%language' => t($form_state['values']['name']), '@locale-help' => url('admin/help/locale'))));
00319 }
00320 else {
00321
00322 $predefined = _locale_get_predefined_list();
00323 locale_add_language($langcode);
00324 drupal_set_message(t('The language %language has been created and can now be used. More information is available on the <a href="@locale-help">help screen</a>.', array('%language' => t($predefined[$langcode][0]), '@locale-help' => url('admin/help/locale'))));
00325 }
00326
00327
00328
00329 if ($batch = locale_batch_by_language($langcode, '_locale_batch_language_finished')) {
00330 batch_set($batch);
00331 }
00332
00333 $form_state['redirect'] = 'admin/settings/language';
00334 return;
00335 }
00336
00340 function locale_languages_edit_form_validate($form, &$form_state) {
00341 if (!empty($form_state['values']['domain']) && !empty($form_state['values']['prefix'])) {
00342 form_set_error('prefix', t('Domain and path prefix values should not be set at the same time.'));
00343 }
00344 if (!empty($form_state['values']['domain']) && $duplicate = db_fetch_object(db_query("SELECT language FROM {languages} WHERE domain = '%s' AND language != '%s'", $form_state['values']['domain'], $form_state['values']['langcode']))) {
00345 form_set_error('domain', t('The domain (%domain) is already tied to a language (%language).', array('%domain' => $form_state['values']['domain'], '%language' => $duplicate->language)));
00346 }
00347 if (empty($form_state['values']['prefix']) && language_default('language') != $form_state['values']['langcode'] && empty($form_state['values']['domain'])) {
00348 form_set_error('prefix', t('Only the default language can have both the domain and prefix empty.'));
00349 }
00350 if (!empty($form_state['values']['prefix']) && $duplicate = db_fetch_object(db_query("SELECT language FROM {languages} WHERE prefix = '%s' AND language != '%s'", $form_state['values']['prefix'], $form_state['values']['langcode']))) {
00351 form_set_error('prefix', t('The prefix (%prefix) is already tied to a language (%language).', array('%prefix' => $form_state['values']['prefix'], '%language' => $duplicate->language)));
00352 }
00353 }
00354
00358 function locale_languages_edit_form_submit($form, &$form_state) {
00359 db_query("UPDATE {languages} SET name = '%s', native = '%s', domain = '%s', prefix = '%s', direction = %d WHERE language = '%s'", $form_state['values']['name'], $form_state['values']['native'], $form_state['values']['domain'], $form_state['values']['prefix'], $form_state['values']['direction'], $form_state['values']['langcode']);
00360 $default = language_default();
00361 if ($default->language == $form_state['values']['langcode']) {
00362 $properties = array('name', 'native', 'direction', 'enabled', 'plurals', 'formula', 'domain', 'prefix', 'weight');
00363 foreach ($properties as $keyname) {
00364 if (isset($form_state['values'][$keyname])) {
00365 $default->$keyname = $form_state['values'][$keyname];
00366 }
00367 }
00368 variable_set('language_default', $default);
00369 }
00370 $form_state['redirect'] = 'admin/settings/language';
00371 return;
00372 }
00385 function locale_languages_delete_form(&$form_state, $langcode) {
00386
00387
00388 if ($langcode == 'en') {
00389 drupal_set_message(t('The English language cannot be deleted.'));
00390 drupal_goto('admin/settings/language');
00391 }
00392
00393 if (language_default('language') == $langcode) {
00394 drupal_set_message(t('The default language cannot be deleted.'));
00395 drupal_goto('admin/settings/language');
00396 }
00397
00398
00399 $languages = language_list();
00400
00401 if (!isset($languages[$langcode])) {
00402 drupal_not_found();
00403 }
00404 else {
00405 $form['langcode'] = array('#type' => 'value', '#value' => $langcode);
00406 return confirm_form($form, t('Are you sure you want to delete the language %name?', array('%name' => t($languages[$langcode]->name))), 'admin/settings/language', t('Deleting a language will remove all interface translations associated with it, and posts in this language will be set to be language neutral. This action cannot be undone.'), t('Delete'), t('Cancel'));
00407 }
00408 }
00409
00413 function locale_languages_delete_form_submit($form, &$form_state) {
00414 $languages = language_list();
00415 if (isset($languages[$form_state['values']['langcode']])) {
00416
00417 db_query("DELETE FROM {locales_target} WHERE language = '%s'", $form_state['values']['langcode']);
00418 cache_clear_all('locale:' . $form_state['values']['langcode'], 'cache');
00419
00420 _locale_rebuild_js($form_state['values']['langcode']);
00421
00422 db_query("DELETE FROM {languages} WHERE language = '%s'", $form_state['values']['langcode']);
00423 db_query("UPDATE {node} SET language = '' WHERE language = '%s'", $form_state['values']['langcode']);
00424 $variables = array('%locale' => $languages[$form_state['values']['langcode']]->name);
00425 drupal_set_message(t('The language %locale has been removed.', $variables));
00426 watchdog('locale', 'The language %locale has been removed.', $variables);
00427 }
00428
00429
00430 cache_clear_all('*', 'cache_page', TRUE);
00431
00432 $form_state['redirect'] = 'admin/settings/language';
00433 return;
00434 }
00447 function locale_languages_configure_form() {
00448 $form['language_negotiation'] = array(
00449 '#title' => t('Language negotiation'),
00450 '#type' => 'radios',
00451 '#options' => array(
00452 LANGUAGE_NEGOTIATION_NONE => t('None.'),
00453 LANGUAGE_NEGOTIATION_PATH_DEFAULT => t('Path prefix only.'),
00454 LANGUAGE_NEGOTIATION_PATH => t('Path prefix with language fallback.'),
00455 LANGUAGE_NEGOTIATION_DOMAIN => t('Domain name only.')),
00456 '#default_value' => variable_get('language_negotiation', LANGUAGE_NEGOTIATION_NONE),
00457 '#description' => t("Select the mechanism used to determine your site's presentation language. <strong>Modifying this setting may break all incoming URLs and should be used with caution in a production environment.</strong>")
00458 );
00459 $form['submit'] = array(
00460 '#type' => 'submit',
00461 '#value' => t('Save settings')
00462 );
00463 return $form;
00464 }
00465
00469 function locale_languages_configure_form_submit($form, &$form_state) {
00470 variable_set('language_negotiation', $form_state['values']['language_negotiation']);
00471 drupal_set_message(t('Language negotiation configuration saved.'));
00472 $form_state['redirect'] = 'admin/settings/language';
00473 return;
00474 }
00487 function locale_translate_overview_screen() {
00488 $languages = language_list('language', TRUE);
00489 $groups = module_invoke_all('locale', 'groups');
00490
00491
00492 $headers = array_merge(array(t('Language')), array_values($groups));
00493
00494
00495 $sums = db_query("SELECT COUNT(*) AS strings, textgroup FROM {locales_source} GROUP BY textgroup");
00496 $groupsums = array();
00497 while ($group = db_fetch_object($sums)) {
00498 $groupsums[$group->textgroup] = $group->strings;
00499 }
00500
00501
00502 $rows = array();
00503 foreach ($languages as $langcode => $language) {
00504 $rows[$langcode] = array('name' => ($langcode == 'en' ? t('English (built-in)') : t($language->name)));
00505 foreach ($groups as $group => $name) {
00506 $rows[$langcode][$group] = ($langcode == 'en' ? t('n/a') : '0/' . (isset($groupsums[$group]) ? $groupsums[$group] : 0) . ' (0%)');
00507 }
00508 }
00509
00510
00511 $translations = db_query("SELECT COUNT(*) AS translation, t.language, s.textgroup FROM {locales_source} s INNER JOIN {locales_target} t ON s.lid = t.lid GROUP BY textgroup, language");
00512 while ($data = db_fetch_object($translations)) {
00513 $ratio = (!empty($groupsums[$data->textgroup]) && $data->translation > 0) ? round(($data->translation/$groupsums[$data->textgroup])*100., 2) : 0;
00514 $rows[$data->language][$data->textgroup] = $data->translation . '/' . $groupsums[$data->textgroup] . " ($ratio%)";
00515 }
00516
00517 return theme('table', $headers, $rows);
00518 }
00531 function locale_translate_seek_screen() {
00532 $output = _locale_translate_seek();
00533 $output .= drupal_get_form('locale_translate_seek_form');
00534 return $output;
00535 }
00536
00540 function locale_translate_seek_form() {
00541
00542 $languages = locale_language_list('name', TRUE);
00543 unset($languages['en']);
00544
00545
00546 $query = _locale_translate_seek_query();
00547 $form = array();
00548 $form['search'] = array('#type' => 'fieldset',
00549 '#title' => t('Search'),
00550 );
00551 $form['search']['string'] = array('#type' => 'textfield',
00552 '#title' => t('String contains'),
00553 '#default_value' => @$query['string'],
00554 '#description' => t('Leave blank to show all strings. The search is case sensitive.'),
00555 );
00556 $form['search']['language'] = array(
00557
00558
00559 '#type' => (count($languages) <= 3 ? 'radios' : 'select'),
00560 '#title' => t('Language'),
00561 '#default_value' => (!empty($query['language']) ? $query['language'] : 'all'),
00562 '#options' => array_merge(array('all' => t('All languages'), 'en' => t('English (provided by Drupal)')), $languages),
00563 );
00564 $form['search']['translation'] = array('#type' => 'radios',
00565 '#title' => t('Search in'),
00566 '#default_value' => (!empty($query['translation']) ? $query['translation'] : 'all'),
00567 '#options' => array('all' => t('Both translated and untranslated strings'), 'translated' => t('Only translated strings'), 'untranslated' => t('Only untranslated strings')),
00568 );
00569 $groups = module_invoke_all('locale', 'groups');
00570 $form['search']['group'] = array('#type' => 'radios',
00571 '#title' => t('Limit search to'),
00572 '#default_value' => (!empty($query['group']) ? $query['group'] : 'all'),
00573 '#options' => array_merge(array('all' => t('All text groups')), $groups),
00574 );
00575
00576 $form['search']['submit'] = array('#type' => 'submit', '#value' => t('Search'));
00577 $form['#redirect'] = FALSE;
00578
00579 return $form;
00580 }
00593 function locale_translate_import_form() {
00594
00595 $names = locale_language_list('name', TRUE);
00596 unset($names['en']);
00597
00598 if (!count($names)) {
00599 $languages = _locale_prepare_predefined_list();
00600 $default = array_shift(array_keys($languages));
00601 }
00602 else {
00603 $languages = array(
00604 t('Already added languages') => $names,
00605 t('Languages not yet added') => _locale_prepare_predefined_list()
00606 );
00607 $default = array_shift(array_keys($names));
00608 }
00609
00610 $form = array();
00611 $form['import'] = array('#type' => 'fieldset',
00612 '#title' => t('Import translation'),
00613 );
00614 $form['import']['file'] = array('#type' => 'file',
00615 '#title' => t('Language file'),
00616 '#size' => 50,
00617 '#description' => t('A Gettext Portable Object (<em>.po</em>) file.'),
00618 );
00619 $form['import']['langcode'] = array('#type' => 'select',
00620 '#title' => t('Import into'),
00621 '#options' => $languages,
00622 '#default_value' => $default,
00623 '#description' => t('Choose the language you want to add strings into. If you choose a language which is not yet set up, it will be added.'),
00624 );
00625 $form['import']['group'] = array('#type' => 'radios',
00626 '#title' => t('Text group'),
00627 '#default_value' => 'default',
00628 '#options' => module_invoke_all('locale', 'groups'),
00629 '#description' => t('Imported translations will be added to this text group.'),
00630 );
00631 $form['import']['mode'] = array('#type' => 'radios',
00632 '#title' => t('Mode'),
00633 '#default_value' => LOCALE_IMPORT_KEEP,
00634 '#options' => array(
00635 LOCALE_IMPORT_OVERWRITE => t('Strings in the uploaded file replace existing ones, new ones are added'),
00636 LOCALE_IMPORT_KEEP => t('Existing strings are kept, only new strings are added')
00637 ),
00638 );
00639 $form['import']['submit'] = array('#type' => 'submit', '#value' => t('Import'));
00640 $form['#attributes']['enctype'] = 'multipart/form-data';
00641
00642 return $form;
00643 }
00644
00648 function locale_translate_import_form_submit($form, &$form_state) {
00649
00650 if ($file = file_save_upload('file')) {
00651
00652
00653 $languages = language_list('language', TRUE);
00654 $langcode = $form_state['values']['langcode'];
00655 if (!isset($languages[$langcode])) {
00656 $predefined = _locale_get_predefined_list();
00657 locale_add_language($langcode);
00658 drupal_set_message(t('The language %language has been created.', array('%language' => t($predefined[$langcode][0]))));
00659 }
00660
00661
00662 if ($ret = _locale_import_po($file, $langcode, $form_state['values']['mode'], $form_state['values']['group']) == FALSE) {
00663 $variables = array('%filename' => $file->filename);
00664 drupal_set_message(t('The translation import of %filename failed.', $variables), 'error');
00665 watchdog('locale', 'The translation import of %filename failed.', $variables, WATCHDOG_ERROR);
00666 }
00667 }
00668 else {
00669 drupal_set_message(t('File to import not found.'), 'error');
00670 return 'admin/build/translate/import';
00671 }
00672
00673 $form_state['redirect'] = 'admin/build/translate';
00674 return;
00675 }
00688 function locale_translate_export_screen() {
00689
00690 $names = locale_language_list('name', TRUE);
00691 unset($names['en']);
00692 $output = '';
00693
00694 if (count($names)) {
00695 $output = drupal_get_form('locale_translate_export_po_form', $names);
00696 }
00697 $output .= drupal_get_form('locale_translate_export_pot_form');
00698 return $output;
00699 }
00700
00707 function locale_translate_export_po_form(&$form_state, $names) {
00708 $form['export'] = array('#type' => 'fieldset',
00709 '#title' => t('Export translation'),
00710 '#collapsible' => TRUE,
00711 );
00712 $form['export']['langcode'] = array('#type' => 'select',
00713 '#title' => t('Language name'),
00714 '#options' => $names,
00715 '#description' => t('Select the language to export in Gettext Portable Object (<em>.po</em>) format.'),
00716 );
00717 $form['export']['group'] = array('#type' => 'radios',
00718 '#title' => t('Text group'),
00719 '#default_value' => 'default',
00720 '#options' => module_invoke_all('locale', 'groups'),
00721 );
00722 $form['export']['submit'] = array('#type' => 'submit', '#value' => t('Export'));
00723 return $form;
00724 }
00725
00729 function locale_translate_export_pot_form() {
00730
00731 $form['export'] = array('#type' => 'fieldset',
00732 '#title' => t('Export template'),
00733 '#collapsible' => TRUE,
00734 '#description' => t('Generate a Gettext Portable Object Template (<em>.pot</em>) file with all strings from the Drupal locale database.'),
00735 );
00736 $form['export']['group'] = array('#type' => 'radios',
00737 '#title' => t('Text group'),
00738 '#default_value' => 'default',
00739 '#options' => module_invoke_all('locale', 'groups'),
00740 );
00741 $form['export']['submit'] = array('#type' => 'submit', '#value' => t('Export'));
00742
00743 $form['#submit'][] = 'locale_translate_export_po_form_submit';
00744 $form['#validate'][] = 'locale_translate_export_po_form_validate';
00745 return $form;
00746 }
00747
00751 function locale_translate_export_po_form_submit($form, &$form_state) {
00752
00753 $language = NULL;
00754 if (isset($form_state['values']['langcode'])) {
00755 $languages = language_list();
00756 $language = $languages[$form_state['values']['langcode']];
00757 }
00758 _locale_export_po($language, _locale_export_po_generate($language, _locale_export_get_strings($language, $form_state['values']['group'])));
00759 }
00772 function locale_translate_edit_form(&$form_state, $lid) {
00773
00774 $source = db_fetch_object(db_query('SELECT source, textgroup, location FROM {locales_source} WHERE lid = %d', $lid));
00775 if (!$source) {
00776 drupal_set_message(t('String not found.'), 'error');
00777 drupal_goto('admin/build/translate/search');
00778 }
00779
00780
00781 $form = array(
00782 'original' => array(
00783 '#type' => 'item',
00784 '#title' => t('Original text'),
00785 '#value' => check_plain(wordwrap($source->source, 0)),
00786 ),
00787 'lid' => array(
00788 '#type' => 'value',
00789 '#value' => $lid
00790 ),
00791 'textgroup' => array(
00792 '#type' => 'value',
00793 '#value' => $source->textgroup,
00794 ),
00795 'location' => array(
00796 '#type' => 'value',
00797 '#value' => $source->location
00798 ),
00799 );
00800
00801
00802
00803 $languages = language_list();
00804 $default = language_default();
00805
00806 $omit = $source->textgroup == 'default' ? 'en' : $default->language;
00807 unset($languages[($omit)]);
00808 $form['translations'] = array('#tree' => TRUE);
00809
00810 $rows = min(ceil(str_word_count($source->source) / 12), 10);
00811 foreach ($languages as $langcode => $language) {
00812 $form['translations'][$langcode] = array(
00813 '#type' => 'textarea',
00814 '#title' => t($language->name),
00815 '#rows' => $rows,
00816 '#default_value' => '',
00817 );
00818 }
00819
00820
00821 $result = db_query("SELECT DISTINCT translation, language FROM {locales_target} WHERE lid = %d AND language != '%s'", $lid, $omit);
00822 while ($translation = db_fetch_object($result)) {
00823 $form['translations'][$translation->language]['#default_value'] = $translation->translation;
00824 }
00825
00826 $form['submit'] = array('#type' => 'submit', '#value' => t('Save translations'));
00827 return $form;
00828 }
00829
00834 function locale_translate_edit_form_submit($form, &$form_state) {
00835 $lid = $form_state['values']['lid'];
00836 foreach ($form_state['values']['translations'] as $key => $value) {
00837 $translation = db_result(db_query("SELECT translation FROM {locales_target} WHERE lid = %d AND language = '%s'", $lid, $key));
00838 if (!empty($value)) {
00839
00840 if (!empty($translation)) {
00841 db_query("UPDATE {locales_target} SET translation = '%s' WHERE lid = %d AND language = '%s'", $value, $lid, $key);
00842 }
00843 else {
00844 db_query("INSERT INTO {locales_target} (lid, translation, language) VALUES (%d, '%s', '%s')", $lid, $value, $key);
00845 }
00846 }
00847 elseif (!empty($translation)) {
00848
00849 db_query("DELETE FROM {locales_target} WHERE lid = %d AND language = '%s'", $lid, $key);
00850 }
00851
00852
00853 _locale_invalidate_js($key);
00854 }
00855
00856 drupal_set_message(t('The string has been saved.'));
00857
00858
00859 cache_clear_all('locale:', 'cache', TRUE);
00860
00861 $form_state['redirect'] = 'admin/build/translate/search';
00862 return;
00863 }
00876 function locale_translate_delete($lid) {
00877 db_query('DELETE FROM {locales_source} WHERE lid = %d', $lid);
00878 db_query('DELETE FROM {locales_target} WHERE lid = %d', $lid);
00879
00880 _locale_invalidate_js();
00881 cache_clear_all('locale:', 'cache', TRUE);
00882 drupal_set_message(t('The string has been removed.'));
00883 drupal_goto('admin/build/translate/search');
00884 }
00916 function locale_add_language($langcode, $name = NULL, $native = NULL, $direction = LANGUAGE_LTR, $domain = '', $prefix = '', $enabled = TRUE, $default = FALSE) {
00917
00918 if (empty($prefix)) {
00919 $prefix = $langcode;
00920 }
00921
00922
00923 if (!isset($name)) {
00924 $predefined = _locale_get_predefined_list();
00925 $name = $predefined[$langcode][0];
00926 $native = isset($predefined[$langcode][1]) ? $predefined[$langcode][1] : $predefined[$langcode][0];
00927 $direction = isset($predefined[$langcode][2]) ? $predefined[$langcode][2] : LANGUAGE_LTR;
00928 }
00929
00930 db_query("INSERT INTO {languages} (language, name, native, direction, domain, prefix, enabled) VALUES ('%s', '%s', '%s', %d, '%s', '%s', %d)", $langcode, $name, $native, $direction, $domain, $prefix, $enabled);
00931
00932
00933 if ($enabled && $default) {
00934 variable_set('language_default', (object) array('language' => $langcode, 'name' => $name, 'native' => $native, 'direction' => $direction, 'enabled' => (int) $enabled, 'plurals' => 0, 'formula' => '', 'domain' => '', 'prefix' => $prefix, 'weight' => 0, 'javascript' => ''));
00935 }
00936
00937 if ($enabled) {
00938
00939 variable_set('language_count', variable_get('language_count', 1) + 1);
00940 }
00941
00942
00943 _locale_invalidate_js($langcode);
00944
00945 watchdog('locale', 'The %language language (%code) has been created.', array('%language' => $name, '%code' => $langcode));
00946 }
00968 function _locale_import_po($file, $langcode, $mode, $group = NULL) {
00969
00970 if (!ini_get('safe_mode')) {
00971 set_time_limit(240);
00972 }
00973
00974
00975 if (!db_fetch_object(db_query("SELECT language FROM {languages} WHERE language = '%s'", $langcode))) {
00976 drupal_set_message(t('The language selected for import is not supported.'), 'error');
00977 return FALSE;
00978 }
00979
00980
00981 $status = _locale_import_read_po('db-store', $file, $mode, $langcode, $group);
00982 if ($status === FALSE) {
00983
00984 return FALSE;
00985 }
00986
00987
00988 list($headerdone, $additions, $updates, $deletes) = _locale_import_one_string('db-report');
00989
00990 if (!$headerdone) {
00991 drupal_set_message(t('The translation file %filename appears to have a missing or malformed header.', array('%filename' => $file->filename)), 'error');
00992 }
00993
00994
00995 _locale_invalidate_js($langcode);
00996 cache_clear_all('locale:', 'cache', TRUE);
00997
00998
00999 menu_rebuild();
01000
01001 drupal_set_message(t('The translation was successfully imported. There are %number newly created translated strings, %update strings were updated and %delete strings were removed.', array('%number' => $additions, '%update' => $updates, '%delete' => $deletes)));
01002 watchdog('locale', 'Imported %file into %locale: %number new strings added, %update updated and %delete removed.', array('%file' => $file->filename, '%locale' => $langcode, '%number' => $additions, '%update' => $updates, '%delete' => $deletes));
01003 return TRUE;
01004 }
01005
01020 function _locale_import_read_po($op, $file, $mode = NULL, $lang = NULL, $group = 'default') {
01021
01022 $fd = fopen($file->filepath, "rb");
01023 if (!$fd) {
01024 _locale_import_message('The translation import failed, because the file %filename could not be read.', $file);
01025 return FALSE;
01026 }
01027
01028 $context = "COMMENT";
01029 $current = array();
01030 $plural = 0;
01031 $lineno = 0;
01032
01033 while (!feof($fd)) {
01034 $line = fgets($fd, 10*1024);
01035 if ($lineno == 0) {
01036
01037 $line = str_replace("\xEF\xBB\xBF", '', $line);
01038 }
01039 $lineno++;
01040 $line = trim(strtr($line, array("\\\n" => "")));
01041
01042 if (!strncmp("#", $line, 1)) {
01043 if ($context == "COMMENT") {
01044 $current["#"][] = substr($line, 1);
01045 }
01046 elseif (($context == "MSGSTR") || ($context == "MSGSTR_ARR")) {
01047 _locale_import_one_string($op, $current, $mode, $lang, $file, $group);
01048 $current = array();
01049 $current["#"][] = substr($line, 1);
01050 $context = "COMMENT";
01051 }
01052 else {
01053 _locale_import_message('The translation file %filename contains an error: "msgstr" was expected but not found on line %line.', $file, $lineno);
01054 return FALSE;
01055 }
01056 }
01057 elseif (!strncmp("msgid_plural", $line, 12)) {
01058 if ($context != "MSGID") {
01059 _locale_import_message('The translation file %filename contains an error: "msgid_plural" was expected but not found on line %line.', $file, $lineno);
01060 return FALSE;
01061 }
01062 $line = trim(substr($line, 12));
01063 $quoted = _locale_import_parse_quoted($line);
01064 if ($quoted === FALSE) {
01065 _locale_import_message('The translation file %filename contains a syntax error on line %line.', $file, $lineno);
01066 return FALSE;
01067 }
01068 $current["msgid"] = $current["msgid"] . "\0" . $quoted;
01069 $context = "MSGID_PLURAL";
01070 }
01071 elseif (!strncmp("msgid", $line, 5)) {
01072 if ($context == "MSGSTR") {
01073 _locale_import_one_string($op, $current, $mode, $lang, $file, $group);
01074 $current = array();
01075 }
01076 elseif ($context == "MSGID") {
01077 _locale_import_message('The translation file %filename contains an error: "msgid" is unexpected on line %line.', $file, $lineno);
01078 return FALSE;
01079 }
01080 $line = trim(substr($line, 5));
01081 $quoted = _locale_import_parse_quoted($line);
01082 if ($quoted === FALSE) {
01083 _locale_import_message('The translation file %filename contains a syntax error on line %line.', $file, $lineno);
01084 return FALSE;
01085 }
01086 $current["msgid"] = $quoted;
01087 $context = "MSGID";
01088 }
01089 elseif (!strncmp("msgstr[", $line, 7)) {
01090 if (($context != "MSGID") && ($context != "MSGID_PLURAL") && ($context != "MSGSTR_ARR")) {
01091 _locale_import_message('The translation file %filename contains an error: "msgstr[]" is unexpected on line %line.', $file, $lineno);
01092 return FALSE;
01093 }
01094 if (strpos($line, "]") === FALSE) {
01095 _locale_import_message('The translation file %filename contains a syntax error on line %line.', $file, $lineno);
01096 return FALSE;
01097 }
01098 $frombracket = strstr($line, "[");
01099 $plural = substr($frombracket, 1, strpos($frombracket, "]") - 1);
01100 $line = trim(strstr($line, " "));
01101 $quoted = _locale_import_parse_quoted($line);
01102 if ($quoted === FALSE) {
01103 _locale_import_message('The translation file %filename contains a syntax error on line %line.', $file, $lineno);
01104 return FALSE;
01105 }
01106 $current["msgstr"][$plural] = $quoted;
01107 $context = "MSGSTR_ARR";
01108 }
01109 elseif (!strncmp("msgstr", $line, 6)) {
01110 if ($context != "MSGID") {
01111 _locale_import_message('The translation file %filename contains an error: "msgstr" is unexpected on line %line.', $file, $lineno);
01112 return FALSE;
01113 }
01114 $line = trim(substr($line, 6));
01115 $quoted = _locale_import_parse_quoted($line);
01116 if ($quoted === FALSE) {
01117 _locale_import_message('The translation file %filename contains a syntax error on line %line.', $file, $lineno);
01118 return FALSE;
01119 }
01120 $current["msgstr"] = $quoted;
01121 $context = "MSGSTR";
01122 }
01123 elseif ($line != "") {
01124 $quoted = _locale_import_parse_quoted($line);
01125 if ($quoted === FALSE) {
01126 _locale_import_message('The translation file %filename contains a syntax error on line %line.', $file, $lineno);
01127 return FALSE;
01128 }
01129 if (($context == "MSGID") || ($context == "MSGID_PLURAL")) {
01130 $current["msgid"] .= $quoted;
01131 }
01132 elseif ($context == "MSGSTR") {
01133 $current["msgstr"] .= $quoted;
01134 }
01135 elseif ($context == "MSGSTR_ARR") {
01136 $current["msgstr"][$plural] .= $quoted;
01137 }
01138 else {
01139 _locale_import_message('The translation file %filename contains an error: there is an unexpected string on line %line.', $file, $lineno);
01140 return FALSE;
01141 }
01142 }
01143 }
01144
01145
01146 if (($context == "MSGSTR") || ($context == "MSGSTR_ARR")) {
01147 _locale_import_one_string($op, $current, $mode, $lang, $file, $group);
01148 }
01149 elseif ($context != "COMMENT") {
01150 _locale_import_message('The translation file %filename ended unexpectedly at line %line.', $file, $lineno);
01151 return FALSE;
01152 }
01153
01154 }
01155
01166 function _locale_import_message($message, $file, $lineno = NULL) {
01167 $vars = array('%filename' => $file->filename);
01168 if (isset($lineno)) {
01169 $vars['%line'] = $lineno;
01170 }
01171 $t = get_t();
01172 drupal_set_message($t($message, $vars), 'error');
01173 }
01174
01191 function _locale_import_one_string($op, $value = NULL, $mode = NULL, $lang = NULL, $file = NULL, $group = 'default') {
01192 static $report = array(0, 0, 0);
01193 static $headerdone = FALSE;
01194 static $strings = array();
01195
01196 switch ($op) {
01197
01198 case 'mem-report':
01199 return $strings;
01200
01201
01202 case 'mem-store':
01203 $strings[$value['msgid']] = $value['msgstr'];
01204 return;
01205
01206
01207 case 'db-report':
01208 return array($headerdone, $report[0], $report[1], $report[2]);
01209
01210
01211 case 'db-store':
01212
01213 if ($value['msgid'] == '') {
01214 $header = _locale_import_parse_header($value['msgstr']);
01215
01216
01217 if (isset($header["Plural-Forms"]) && $p = _locale_import_parse_plural_forms($header["Plural-Forms"], $file->filename)) {
01218 list($nplurals, $plural) = $p;
01219 db_query("UPDATE {languages} SET plurals = %d, formula = '%s' WHERE language = '%s'", $nplurals, $plural, $lang);
01220 }
01221 else {
01222 db_query("UPDATE {languages} SET plurals = %d, formula = '%s' WHERE language = '%s'", 0, '', $lang);
01223 }
01224 $headerdone = TRUE;
01225 }
01226
01227 else {
01228
01229 $comments = _locale_import_shorten_comments(empty($value['#']) ? array() : $value['#']);
01230
01231 if (strpos($value['msgid'], "\0")) {
01232
01233 $english = explode("\0", $value['msgid'], 2);
01234 $entries = array_keys($value['msgstr']);
01235 for ($i = 3; $i <= count($entries); $i++) {
01236 $english[] = $english[1];
01237 }
01238 $translation = array_map('_locale_import_append_plural', $value['msgstr'], $entries);
01239 $english = array_map('_locale_import_append_plural', $english, $entries);
01240 foreach ($translation as $key => $trans) {
01241 if ($key == 0) {
01242 $plid = 0;
01243 }
01244 $plid = _locale_import_one_string_db($report, $lang, $english[$key], $trans, $group, $comments, $mode, $plid, $key);
01245 }
01246 }
01247
01248 else {
01249
01250 $english = $value['msgid'];
01251 $translation = $value['msgstr'];
01252 _locale_import_one_string_db($report, $lang, $english, $translation, $group, $comments, $mode);
01253 }
01254 }
01255 }
01256 }
01257
01283 function _locale_import_one_string_db(&$report, $langcode, $source, $translation, $textgroup, $location, $mode, $plid = NULL, $plural = NULL) {
01284 $lid = db_result(db_query("SELECT lid FROM {locales_source} WHERE source = '%s' AND textgroup = '%s'", $source, $textgroup));
01285
01286 if (!empty($translation)) {
01287 if ($lid) {
01288
01289 db_query("UPDATE {locales_source} SET location = '%s' WHERE lid = %d", $location, $lid);
01290 $exists = (bool) db_result(db_query("SELECT lid FROM {locales_target} WHERE lid = %d AND language = '%s'", $lid, $langcode));
01291 if (!$exists) {
01292
01293 db_query("INSERT INTO {locales_target} (lid, language, translation, plid, plural) VALUES (%d, '%s', '%s', %d, %d)", $lid, $langcode, $translation, $plid, $plural);
01294 $report[0]++;
01295 }
01296 else if ($mode == LOCALE_IMPORT_OVERWRITE) {
01297
01298 db_query("UPDATE {locales_target} SET translation = '%s', plid = %d, plural = %d WHERE language = '%s' AND lid = %d", $translation, $plid, $plural, $langcode, $lid);
01299 $report[1]++;
01300 }
01301 }
01302 else {
01303
01304 db_query("INSERT INTO {locales_source} (location, source, textgroup) VALUES ('%s', '%s', '%s')", $location, $source, $textgroup);
01305 $lid = db_result(db_query("SELECT lid FROM {locales_source} WHERE source = '%s' AND textgroup = '%s'", $source, $textgroup));
01306 db_query("INSERT INTO {locales_target} (lid, language, translation, plid, plural) VALUES (%d, '%s', '%s', %d, %d)", $lid, $langcode, $translation, $plid, $plural);
01307 $report[0]++;
01308 }
01309 }
01310 elseif ($mode == LOCALE_IMPORT_OVERWRITE) {
01311
01312 db_query("DELETE FROM {locales_target} WHERE language = '%s' AND lid = %d AND plid = %d AND plural = %d", $translation, $langcode, $lid, $plid, $plural);
01313 $report[2]++;
01314 }
01315
01316 return $lid;
01317 }
01318
01327 function _locale_import_parse_header($header) {
01328 $header_parsed = array();
01329 $lines = array_map('trim', explode("\n", $header));
01330 foreach ($lines as $line) {
01331 if ($line) {
01332 list($tag, $contents) = explode(":", $line, 2);
01333 $header_parsed[trim($tag)] = trim($contents);
01334 }
01335 }
01336 return $header_parsed;
01337 }
01338
01350 function _locale_import_parse_plural_forms($pluralforms, $filename) {
01351
01352 $pluralforms = strtr($pluralforms, array(" " => "", "\t" => ""));
01353
01354
01355 $nplurals = strstr($pluralforms, "nplurals=");
01356 if (strpos($nplurals, ";")) {
01357 $nplurals = substr($nplurals, 9, strpos($nplurals, ";") - 9);
01358 }
01359 else {
01360 return FALSE;
01361 }
01362 $plural = strstr($pluralforms, "plural=");
01363 if (strpos($plural, ";")) {
01364 $plural = substr($plural, 7, strpos($plural, ";") - 7);
01365 }
01366 else {
01367 return FALSE;
01368 }
01369
01370
01371 $plural = _locale_import_parse_arithmetic($plural);
01372
01373 if ($plural !== FALSE) {
01374 return array($nplurals, $plural);
01375 }
01376 else {
01377 drupal_set_message(t('The translation file %filename contains an error: the plural formula could not be parsed.', array('%filename' => $filename)), 'error');
01378 return FALSE;
01379 }
01380 }
01381
01393 function _locale_import_parse_arithmetic($string) {
01394
01395 $prec = array("(" => -1, ")" => -1, "?" => 1, ":" => 1, "||" => 3, "&&" => 4, "==" => 5, "!=" => 5, "<" => 6, ">" => 6, "<=" => 6, ">=" => 6, "+" => 7, "-" => 7, "*" => 8, "/" => 8, "%" => 8);
01396
01397 $rasc = array("?" => 1, ":" => 1);
01398
01399 $tokens = _locale_import_tokenize_formula($string);
01400
01401
01402 $opstk = array();
01403 $elstk = array();
01404
01405 foreach ($tokens as $token) {
01406 $ctok = $token;
01407
01408
01409 if (is_numeric($token)) {
01410 $elstk[] = $ctok;
01411 }
01412 elseif ($ctok == "n") {
01413 $elstk[] = '$n';
01414 }
01415 elseif ($ctok == "(") {
01416 $opstk[] = $ctok;
01417 }
01418 elseif ($ctok == ")") {
01419 $topop = array_pop($opstk);
01420 while (isset($topop) && ($topop != "(")) {
01421 $elstk[] = $topop;
01422 $topop = array_pop($opstk);
01423 }
01424 }
01425 elseif (!empty($prec[$ctok])) {
01426
01427
01428 $topop = array_pop($opstk);
01429 while (isset($topop) && ($prec[$topop] >= $prec[$ctok]) && !(($prec[$topop] == $prec[$ctok]) && !empty($rasc[$topop]) && !empty($rasc[$ctok]))) {
01430 $elstk[] = $topop;
01431 $topop = array_pop($opstk);
01432 }
01433 if ($topop) {
01434 $opstk[] = $topop;
01435 }
01436 $opstk[] = $ctok;
01437 }
01438 else {
01439 return FALSE;
01440 }
01441 }
01442
01443
01444 $topop = array_pop($opstk);
01445 while ($topop != NULL) {
01446 $elstk[] = $topop;
01447 $topop = array_pop($opstk);
01448 }
01449
01450
01451 $prevsize = count($elstk) + 1;
01452 while (count($elstk) < $prevsize) {
01453 $prevsize = count($elstk);
01454 for ($i = 2; $i < count($elstk); $i++) {
01455 $op = $elstk[$i];
01456 if (!empty($prec[$op])) {
01457 $f = "";
01458 if ($op == ":") {
01459 $f = $elstk[$i - 2] . "):" . $elstk[$i - 1] . ")";
01460 }
01461 elseif ($op == "?") {
01462 $f = "(" . $elstk[$i - 2] . "?(" . $elstk[$i - 1];
01463 }
01464 else {
01465 $f = "(" . $elstk[$i - 2] . $op . $elstk[$i - 1] . ")";
01466 }
01467 array_splice($elstk, $i - 2, 3, $f);
01468 break;
01469 }
01470 }
01471 }
01472
01473
01474 if (count($elstk) == 1) {
01475 return $elstk[0];
01476 }
01477 else {
01478 return FALSE;
01479 }
01480 }
01481
01490 function _locale_import_tokenize_formula($formula) {
01491 $formula = str_replace(" ", "", $formula);
01492 $tokens = array();
01493 for ($i = 0; $i < strlen($formula); $i++) {
01494 if (is_numeric($formula[$i])) {
01495 $num = $formula[$i];
01496 $j = $i + 1;
01497 while ($j < strlen($formula) && is_numeric($formula[$j])) {
01498 $num .= $formula[$j];
01499 $j++;
01500 }
01501 $i = $j - 1;
01502 $tokens[] = $num;
01503 }
01504 elseif ($pos = strpos(" =<>!&|", $formula[$i])) {
01505 $next = $formula[$i + 1];
01506 switch ($pos) {
01507 case 1:
01508 case 2:
01509 case 3:
01510 case 4:
01511 if ($next == '=') {
01512 $tokens[] = $formula[$i] . '=';
01513 $i++;
01514 }
01515 else {
01516 $tokens[] = $formula[$i];
01517 }
01518 break;
01519 case 5:
01520 if ($next == '&') {
01521 $tokens[] = '&&';
01522 $i++;
01523 }
01524 else {
01525 $tokens[] = $formula[$i];
01526 }
01527 break;
01528 case 6:
01529 if ($next == '|') {
01530 $tokens[] = '||';
01531 $i++;
01532 }
01533 else {
01534 $tokens[] = $formula[$i];
01535 }
01536 break;
01537 }
01538 }
01539 else {
01540 $tokens[] = $formula[$i];
01541 }
01542 }
01543 return $tokens;
01544 }
01545
01556 function _locale_import_append_plural($entry, $key) {
01557
01558 if ($key == 0 || $key == 1) {
01559 return $entry;
01560 }
01561
01562
01563 $entry = preg_replace('/(@count)\[[0-9]\]/', '\\1', $entry);
01564 return preg_replace('/(@count)/', "\\1[$key]", $entry);
01565 }
01566
01575 function _locale_import_shorten_comments($comment) {
01576 $comm = '';
01577 while (count($comment)) {
01578 $test = $comm . substr(array_shift($comment), 1) . ', ';
01579 if (strlen($comm) < 130) {
01580 $comm = $test;
01581 }
01582 else {
01583 break;
01584 }
01585 }
01586 return substr($comm, 0, -2);
01587 }
01588
01597 function _locale_import_parse_quoted($string) {
01598 if (substr($string, 0, 1) != substr($string, -1, 1)) {
01599 return FALSE;
01600 }
01601 $quote = substr($string, 0, 1);
01602 $string = substr($string, 1, -1);
01603 if ($quote == '"') {
01604 return stripcslashes($string);
01605 }
01606 elseif ($quote == "'") {
01607 return $string;
01608 }
01609 else {
01610 return FALSE;
01611 }
01612 }
01621 function _locale_parse_js_file($filepath) {
01622 global $language;
01623
01624
01625 $file = file_get_contents($filepath);
01626
01627
01628
01629 preg_match_all('~[^\w]Drupal\s*\.\s*t\s*\(\s*(' . LOCALE_JS_STRING . ')\s*[,\)]~s', $file, $t_matches);
01630
01631
01632 preg_match_all('~[^\w]Drupal\s*\.\s*formatPlural\s*\(\s*.+?\s*,\s*(' . LOCALE_JS_STRING . ')\s*,\s*((?:(?:\'(?:\\\\\'|[^\'])*@count(?:\\\\\'|[^\'])*\'|"(?:\\\\"|[^"])*@count(?:\\\\"|[^"])*")(?:\s*\+\s*)?)+)\s*[,\)]~s', $file, $plural_matches);
01633
01634
01635 $all_matches = array_merge($plural_matches[1], $t_matches[1]);
01636 foreach ($all_matches as $key => $string) {
01637 $strings = array($string);
01638
01639
01640 if (isset($plural_matches[2][$key])) {
01641 $strings[] = $plural_matches[2][$key];
01642 }
01643
01644 foreach ($strings as $key => $string) {
01645
01646 $string = implode('', preg_split('~(?<!\\\\)[\'"]\s*\+\s*[\'"]~s', substr($string, 1, -1)));
01647
01648 $result = db_query("SELECT lid, location FROM {locales_source} WHERE source = '%s' AND textgroup = 'default'", $string);
01649 if ($source = db_fetch_object($result)) {
01650
01651
01652 $locations = preg_split('~\s*;\s*~', $source->location);
01653
01654 if (!in_array($filepath, $locations)) {
01655 $locations[] = $filepath;
01656 $locations = implode('; ', $locations);
01657
01658
01659 db_query("UPDATE {locales_source} SET location = '%s' WHERE lid = %d", $locations, $source->lid);
01660 }
01661 }
01662 else {
01663
01664 db_query("INSERT INTO {locales_source} (location, source, textgroup) VALUES ('%s', '%s', 'default')", $filepath, $string);
01665 }
01666 }
01667 }
01668 }
01669
01686 function _locale_export_get_strings($language = NULL, $group = 'default') {
01687 if (isset($language)) {
01688 $result = db_query("SELECT s.lid, s.source, s.location, t.translation, t.plid, t.plural FROM {locales_source} s LEFT JOIN {locales_target} t ON s.lid = t.lid AND t.language = '%s' WHERE s.textgroup = '%s' ORDER BY t.plid, t.plural", $language->language, $group);
01689 }
01690 else {
01691 $result = db_query("SELECT s.lid, s.source, s.location, t.plid, t.plural FROM {locales_source} s LEFT JOIN {locales_target} t ON s.lid = t.lid WHERE s.textgroup = '%s' ORDER BY t.plid, t.plural", $group);
01692 }
01693 $strings = array();
01694 while ($child = db_fetch_object($result)) {
01695 $string = array(
01696 'comment' => $child->location,
01697 'source' => $child->source,
01698 'translation' => isset($child->translation) ? $child->translation : ''
01699 );
01700 if ($child->plid) {
01701
01702
01703
01704
01705 $string['child'] = TRUE;
01706 $strings[$child->plid]['plural'] = $child->lid;
01707 }
01708 $strings[$child->lid] = $string;
01709 }
01710 return $strings;
01711 }
01712
01726 function _locale_export_po_generate($language = NULL, $strings = array(), $header = NULL) {
01727 global $user;
01728
01729 if (!isset($header)) {
01730 if (isset($language)) {
01731 $header = '# ' . $language->name . ' translation of ' . variable_get('site_name', 'Drupal') . "\n";
01732 $header .= '# Generated by ' . $user->name . ' <' . $user->mail . ">\n";
01733 $header .= "#\n";
01734 $header .= "msgid \"\"\n";
01735 $header .= "msgstr \"\"\n";
01736 $header .= "\"Project-Id-Version: PROJECT VERSION\\n\"\n";
01737 $header .= "\"POT-Creation-Date: " . date("Y-m-d H:iO") . "\\n\"\n";
01738 $header .= "\"PO-Revision-Date: " . date("Y-m-d H:iO") . "\\n\"\n";
01739 $header .= "\"Last-Translator: NAME <EMAIL@ADDRESS>\\n\"\n";
01740 $header .= "\"Language-Team: LANGUAGE <EMAIL@ADDRESS>\\n\"\n";
01741 $header .= "\"MIME-Version: 1.0\\n\"\n";
01742 $header .= "\"Content-Type: text/plain; charset=utf-8\\n\"\n";
01743 $header .= "\"Content-Transfer-Encoding: 8bit\\n\"\n";
01744 if ($language->formula && $language->plurals) {
01745 $header .= "\"Plural-Forms: nplurals=" . $language->plurals . "; plural=" . strtr($language->formula, array('$' => '')) . ";\\n\"\n";
01746 }
01747 }
01748 else {
01749 $header = "# LANGUAGE translation of PROJECT\n";
01750 $header .= "# Copyright (c) YEAR NAME <EMAIL@ADDRESS>\n";
01751 $header .= "#\n";
01752 $header .= "msgid \"\"\n";
01753 $header .= "msgstr \"\"\n";
01754 $header .= "\"Project-Id-Version: PROJECT VERSION\\n\"\n";
01755 $header .= "\"POT-Creation-Date: " . date("Y-m-d H:iO") . "\\n\"\n";
01756 $header .= "\"PO-Revision-Date: YYYY-mm-DD HH:MM+ZZZZ\\n\"\n";
01757 $header .= "\"Last-Translator: NAME <EMAIL@ADDRESS>\\n\"\n";
01758 $header .= "\"Language-Team: LANGUAGE <EMAIL@ADDRESS>\\n\"\n";
01759 $header .= "\"MIME-Version: 1.0\\n\"\n";
01760 $header .= "\"Content-Type: text/plain; charset=utf-8\\n\"\n";
01761 $header .= "\"Content-Transfer-Encoding: 8bit\\n\"\n";
01762 $header .= "\"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\\n\"\n";
01763 }
01764 }
01765
01766 $output = $header . "\n";
01767
01768 foreach ($strings as $lid => $string) {
01769
01770 if (!isset($string['child'])) {
01771 if ($string['comment']) {
01772 $output .= '#: ' . $string['comment'] . "\n";
01773 }
01774 $output .= 'msgid ' . _locale_export_string($string['source']);
01775 if (!empty($string['plural'])) {
01776 $plural = $string['plural'];
01777 $output .= 'msgid_plural ' . _locale_export_string($strings[$plural]['source']);
01778 if (isset($language)) {
01779 $translation = $string['translation'];
01780 for ($i = 0; $i < $language->plurals; $i++) {
01781 $output .= 'msgstr[' . $i . '] ' . _locale_export_string($translation);
01782 if ($plural) {
01783 $translation = _locale_export_remove_plural($strings[$plural]['translation']);
01784 $plural = isset($strings[$plural]['plural']) ? $strings[$plural]['plural'] : 0;
01785 }
01786 else {
01787 $translation = '';
01788 }
01789 }
01790 }
01791 else {
01792 $output .= 'msgstr[0] ""' . "\n";
01793 $output .= 'msgstr[1] ""' . "\n";
01794 }
01795 }
01796 else {
01797 $output .= 'msgstr ' . _locale_export_string($string['translation']);
01798 }
01799 $output .= "\n";
01800 }
01801 }
01802 return $output;
01803 }
01804
01815 function _locale_export_po($language = NULL, $output = NULL) {
01816
01817 if (isset($language)) {
01818 $filename = $language->language . '.po';
01819 watchdog('locale', 'Exported %locale translation file: %filename.', array('%locale' => $language->name, '%filename' => $filename));
01820 }
01821 else {
01822 $filename = 'drupal.pot';
01823 watchdog('locale', 'Exported translation file: %filename.', array('%filename' => $filename));
01824 }
01825
01826 header("Content-Disposition: attachment; filename=$filename");
01827 header("Content-Type: text/plain; charset=utf-8");
01828 print $output;
01829 die();
01830 }
01831
01835 function _locale_export_string($str) {
01836 $stri = addcslashes($str, "\0..\37\\\"");
01837 $parts = array();
01838
01839
01840 while ($stri != "") {
01841 $i = strpos($stri, "\\n");
01842 if ($i === FALSE) {
01843 $curstr = $stri;
01844 $stri = "";
01845 }
01846 else {
01847 $curstr = substr($stri, 0, $i + 2);
01848 $stri = substr($stri, $i + 2);
01849 }
01850 $curparts = explode("\n", _locale_export_wrap($curstr, 70));
01851 $parts = array_merge($parts, $curparts);
01852 }
01853
01854
01855 if (count($parts) > 1) {
01856 return "\"\"\n\"" . implode("\"\n\"", $parts) . "\"\n";
01857 }
01858
01859 elseif (count($parts) == 1) {
01860 return "\"$parts[0]\"\n";
01861 }
01862
01863 else {
01864 return "\"\"\n";
01865 }
01866 }
01867
01871 function _locale_export_wrap($str, $len) {
01872 $words = explode(' ', $str);
01873 $ret = array();
01874
01875 $cur = "";
01876 $nstr = 1;
01877 while (count($words)) {
01878 $word = array_shift($words);
01879 if ($nstr) {
01880 $cur = $word;
01881 $nstr = 0;
01882 }
01883 elseif (strlen("$cur $word") > $len) {
01884 $ret[] = $cur . " ";
01885 $cur = $word;
01886 }
01887 else {
01888 $cur = "$cur $word";
01889 }
01890 }
01891 $ret[] = $cur;
01892
01893 return implode("\n", $ret);
01894 }
01895
01899 function _locale_export_remove_plural($entry) {
01900 return preg_replace('/(@count)\[[0-9]\]/', '\\1', $entry);
01901 }
01914 function _locale_translate_seek() {
01915 $output = '';
01916
01917
01918 if ($query = _locale_translate_seek_query()) {
01919 $join = "SELECT s.source, s.location, s.lid, s.textgroup, t.translation, t.language FROM {locales_source} s LEFT JOIN {locales_target} t ON s.lid = t.lid ";
01920
01921 $arguments = array();
01922 $limit_language = FALSE;
01923
01924 switch ($query['translation']) {
01925 case 'translated':
01926 $where = "WHERE (t.translation LIKE '%%%s%%')";
01927 $orderby = "ORDER BY t.translation";
01928 $arguments[] = $query['string'];
01929 break;
01930 case 'untranslated':
01931 $where = "WHERE (s.source LIKE '%%%s%%' AND t.translation IS NULL)";
01932 $orderby = "ORDER BY s.source";
01933 $arguments[] = $query['string'];
01934 break;
01935 case 'all' :
01936 default:
01937 $where = "WHERE (s.source LIKE '%%%s%%' OR t.translation LIKE '%%%s%%')";
01938 $orderby = '';
01939 $arguments[] = $query['string'];
01940 $arguments[] = $query['string'];
01941 break;
01942 }
01943 $grouplimit = '';
01944 if (!empty($query['group']) && $query['group'] != 'all') {
01945 $grouplimit = " AND s.textgroup = '%s'";
01946 $arguments[] = $query['group'];
01947 }
01948
01949 switch ($query['language']) {
01950
01951 case "en":
01952 $sql = $join . " WHERE s.source LIKE '%%%s%%' $grouplimit ORDER BY s.source";
01953 $arguments = array($query['string']);
01954 if (!empty($grouplimit)) {
01955 $arguments[] = $query['group'];
01956 }
01957 break;
01958
01959 case "all":
01960 $sql = "$join $where $grouplimit $orderby";
01961 break;
01962
01963 default:
01964 $sql = "$join AND t.language = '%s' $where $grouplimit $orderby";
01965 array_unshift($arguments, $query['language']);
01966
01967 $limit_language = $query['language'];
01968 }
01969
01970 $result = pager_query($sql, 50, 0, NULL, $arguments);
01971
01972 $groups = module_invoke_all('locale', 'groups');
01973 $header = array(t('Text group'), t('String'), ($limit_language) ? t('Language') : t('Languages'), array('data' => t('Operations'), 'colspan' => '2'));
01974 $arr = array();
01975 while ($locale = db_fetch_object($result)) {
01976 $arr[$locale->lid]['group'] = $groups[$locale->textgroup];
01977 $arr[$locale->lid]['languages'][$locale->language] = $locale->translation;
01978 $arr[$locale->lid]['location'] = $locale->location;
01979 $arr[$locale->lid]['source'] = $locale->source;
01980 }
01981 $rows = array();
01982 foreach ($arr as $lid => $value) {
01983 $rows[] = array(
01984 $value['group'],
01985 array('data' => check_plain(truncate_utf8($value['source'], 150, FALSE, TRUE)) . '<br /><small>' . $value['location'] . '</small>'),
01986 array('data' => _locale_translate_language_list($value['languages'], $limit_language), 'align' => 'center'),
01987 array('data' => l(t('edit'), "admin/build/translate/edit/$lid"), 'class' => 'nowrap'),
01988 array('data' => l(t('delete'), "admin/build/translate/delete/$lid"), 'class' => 'nowrap'),
01989 );
01990 }
01991
01992 if (count($rows)) {
01993 $output .= theme('table', $header, $rows);
01994 if ($pager = theme('pager', NULL, 50)) {
01995 $output .= $pager;
01996 }
01997 }
01998 else {
01999 $output .= t('No strings found for your search.');
02000 }
02001 }
02002
02003 return $output;
02004 }
02005
02009 function _locale_translate_seek_query() {
02010 static $query = NULL;
02011 if (!isset($query)) {
02012 $query = array();
02013 $fields = array('string', 'language', 'translation', 'group');
02014 foreach ($fields as $field) {
02015 if (isset($_REQUEST[$field])) {
02016 $query[$field] = $_REQUEST[$field];
02017 }
02018 }
02019 }
02020 return $query;
02021 }
02022
02036 function _locale_invalidate_js($langcode = NULL) {
02037 $parsed = variable_get('javascript_parsed', array());
02038
02039 if (empty($langcode)) {
02040
02041 $languages = language_list();
02042 unset($languages['en']);
02043 foreach ($languages as $lcode => $data) {
02044 $parsed['refresh:' . $lcode] = 'waiting';
02045 }
02046 }
02047 else {
02048
02049 $parsed['refresh:' . $langcode] = 'waiting';
02050 }
02051
02052 variable_set('javascript_parsed', $parsed);
02053 return $parsed;
02054 }
02055
02062 function _locale_rebuild_js($langcode = NULL) {
02063 if (!isset($langcode)) {
02064 global $language;
02065 }
02066 else {
02067
02068 $languages = language_list();
02069 $language = $languages[$langcode];
02070 }
02071
02072
02073
02074 $result = db_query("SELECT s.lid, s.source, t.plid, t.plural, t.translation FROM {locales_source} s LEFT JOIN {locales_target} t ON s.lid = t.lid AND t.language = '%s' WHERE s.location LIKE '%%.js%%' AND s.textgroup = 'default' ORDER BY t.plural DESC", $language->language);
02075
02076 $translations = $plurals = array();
02077 while ($data = db_fetch_object($result)) {
02078
02079 if (!empty($data->translation)) {
02080 if ($data->plural) {
02081
02082
02083 if (!isset($plurals[$data->plid])) {
02084 $plurals[$data->plid] = array($data->plural => $data->translation);
02085 }
02086 else {
02087 $plurals[$data->plid] += array($data->plural => $data->translation);
02088 }
02089 }
02090 elseif (isset($plurals[$data->lid])) {
02091
02092
02093 $translations[$data->source] = array($data->plural => $data->translation) + $plurals[$data->lid];
02094 unset($plurals[$data->lid]);
02095 }
02096 else {
02097
02098
02099 $translations[$data->source] = $data->translation;
02100 }
02101 }
02102 }
02103
02104
02105 $data = $status = '';
02106 if (!empty($translations)) {
02107
02108 $data = "Drupal.locale = { ";
02109
02110 if (!empty($language->formula)) {
02111 $data .= "'pluralFormula': function(\$n) { return Number({$language->formula}); }, ";
02112 }
02113
02114 $data .= "'strings': " . drupal_to_js($translations) . " };";
02115 $data_hash = md5($data);
02116 }
02117
02118
02119
02120 $dir = file_create_path(variable_get('locale_js_directory', 'languages'));
02121
02122
02123 if (!empty($language->javascript) && (!$data || $language->javascript != $data_hash)) {
02124 file_delete(file_create_path($dir . '/' . $language->language . '_' . $language->javascript . '.js'));
02125 $language->javascript = '';
02126 $status = 'deleted';
02127 }
02128
02129
02130 if ($data && $language->javascript != $data_hash) {
02131
02132 file_check_directory($dir, TRUE);
02133
02134
02135 $dest = $dir . '/' . $language->language . '_' . $data_hash . '.js';
02136 if (file_save_data($data, $dest)) {
02137 $language->javascript = $data_hash;
02138 $status = ($status == 'deleted') ? 'updated' : 'created';
02139 }
02140 else {
02141 $language->javascript = '';
02142 $status = 'error';
02143 }
02144 }
02145
02146
02147
02148 if ($status) {
02149 db_query("UPDATE {languages} SET javascript = '%s' WHERE language = '%s'", $language->javascript, $language->language);
02150
02151
02152
02153
02154 $default_langcode = language_default('language');
02155 if ($default_langcode == $language->language) {
02156 $default = db_fetch_object(db_query("SELECT * FROM {languages} WHERE language = '%s'", $default_langcode));
02157 variable_set('language_default', $default);
02158 }
02159 }
02160
02161
02162 switch ($status) {
02163 case 'updated':
02164 watchdog('locale', 'Updated JavaScript translation file for the language %language.', array('%language' => t($language->name)));
02165 return TRUE;
02166 case 'created':
02167 watchdog('locale', 'Created JavaScript translation file for the language %language.', array('%language' => t($language->name)));
02168 return TRUE;
02169 case 'deleted':
02170 watchdog('locale', 'Removed JavaScript translation file for the language %language, because no translations currently exist for that language.', array('%language' => t($language->name)));
02171 return TRUE;
02172 case 'error':
02173 watchdog('locale', 'An error occurred during creation of the JavaScript translation file for the language %language.', array('%language' => t($language->name)), WATCHDOG_ERROR);
02174 return FALSE;
02175 default:
02176
02177 return TRUE;
02178 }
02179 }
02180
02184 function _locale_translate_language_list($translation, $limit_language) {
02185
02186 drupal_add_css(drupal_get_path('module', 'locale') . '/locale.css', 'module', 'all', FALSE);
02187
02188 $languages = language_list();
02189 unset($languages['en']);
02190 $output = '';
02191 foreach ($languages as $langcode => $language) {
02192 if (!$limit_language || $limit_language == $langcode) {
02193 $output .= (!empty($translation[$langcode])) ? $langcode . ' ' : "<em class=\"locale-untranslated\">$langcode</em> ";
02194 }
02195 }
02196
02197 return $output;
02198 }
02211 function _locale_prepare_predefined_list() {
02212 $languages = language_list();
02213 $predefined = _locale_get_predefined_list();
02214 foreach ($predefined as $key => $value) {
02215 if (isset($languages[$key])) {
02216 unset($predefined[$key]);
02217 continue;
02218 }
02219
02220 if (count($value) > 1) {
02221 $tname = t($value[0]);
02222 $predefined[$key] = ($tname == $value[1]) ? $tname : "$tname ($value[1])";
02223 }
02224 else {
02225 $predefined[$key] = t($value[0]);
02226 }
02227 }
02228 asort($predefined);
02229 return $predefined;
02230 }
02231
02237 function _locale_get_predefined_list() {
02238 return array(
02239 "aa" => array("Afar"),
02240 "ab" => array("Abkhazian", "аҧсуа бызшәа"),
02241 "ae" => array("Avestan"),
02242 "af" => array("Afrikaans"),
02243 "ak" => array("Akan"),
02244 "am" => array("Amharic", "አማርኛ"),
02245 "ar" => array("Arabic", "العربية", LANGUAGE_RTL),
02246 "as" => array("Assamese"),
02247 "av" => array("Avar"),
02248 "ay" => array("Aymara"),
02249 "az" => array("Azerbaijani", "azərbaycan"),
02250 "ba" => array("Bashkir"),
02251 "be" => array("Belarusian", "Беларуская"),
02252 "bg" => array("Bulgarian", "Български"),
02253 "bh" => array("Bihari"),
02254 "bi" => array("Bislama"),
02255 "bm" => array("Bambara", "Bamanankan"),
02256 "bn" => array("Bengali"),
02257 "bo" => array("Tibetan"),
02258 "br" => array("Breton"),
02259 "bs" => array("Bosnian", "Bosanski"),
02260 "ca" => array("Catalan", "Català"),
02261 "ce" => array("Chechen"),
02262 "ch" => array("Chamorro"),
02263 "co" => array("Corsican"),
02264 "cr" => array("Cree"),
02265 "cs" => array("Czech", "Čeština"),
02266 "cu" => array("Old Slavonic"),
02267 "cv" => array("Chuvash"),
02268 "cy" => array("Welsh", "Cymraeg"),
02269 "da" => array("Danish", "Dansk"),
02270 "de" => array("German", "Deutsch"),
02271 "dv" => array("Maldivian"),
02272 "dz" => array("Bhutani"),
02273 "ee" => array("Ewe", "Ɛʋɛ"),
02274 "el" => array("Greek", "Ελληνικά"),
02275 "en" => array("English"),
02276 "eo" => array("Esperanto"),
02277 "es" => array("Spanish", "Español"),
02278 "et" => array("Estonian", "Eesti"),
02279 "eu" => array("Basque", "Euskera"),
02280 "fa" => array("Persian", "فارسی", LANGUAGE_RTL),
02281 "ff" => array("Fulah", "Fulfulde"),
02282 "fi" => array("Finnish", "Suomi"),
02283 "fj" => array("Fiji"),
02284 "fo" => array("Faeroese"),
02285 "fr" => array("French", "Français"),
02286 "fy" => array("Frisian", "Frysk"),
02287 "ga" => array("Irish", "Gaeilge"),
02288 "gd" => array("Scots Gaelic"),
02289 "gl" => array("Galician", "Galego"),
02290 "gn" => array("Guarani"),
02291 "gu" => array("Gujarati"),
02292 "gv" => array("Manx"),
02293 "ha" => array("Hausa"),
02294 "he" => array("Hebrew", "עברית", LANGUAGE_RTL),
02295 "hi" => array("Hindi", "हिन्दी"),
02296 "ho" => array("Hiri Motu"),
02297 "hr" => array("Croatian", "Hrvatski"),
02298 "hu" => array("Hungarian", "Magyar"),
02299 "hy" => array("Armenian", "Հայերեն"),
02300 "hz" => array("Herero"),
02301 "ia" => array("Interlingua"),
02302 "id" => array("Indonesian", "Bahasa Indonesia"),
02303 "ie" => array("Interlingue"),
02304 "ig" => array("Igbo"),
02305 "ik" => array("Inupiak"),
02306 "is" => array("Icelandic", "Íslenska"),
02307 "it" => array("Italian", "Italiano"),
02308 "iu" => array("Inuktitut"),
02309 "ja" => array("Japanese", "日本語"),
02310 "jv" => array("Javanese"),
02311 "ka" => array("Georgian"),
02312 "kg" => array("Kongo"),
02313 "ki" => array("Kikuyu"),
02314 "kj" => array("Kwanyama"),
02315 "kk" => array("Kazakh", "Қазақ"),
02316 "kl" => array("Greenlandic"),
02317 "km" => array("Cambodian"),
02318 "kn" => array("Kannada", "ಕನ್ನಡ"),
02319 "ko" => array("Korean", "한국어"),
02320 "kr" => array("Kanuri"),
02321 "ks" => array("Kashmiri"),
02322 "ku" => array("Kurdish", "Kurdî"),
02323 "kv" => array("Komi"),
02324 "kw" => array("Cornish"),
02325 "ky" => array("Kirghiz", "Кыргыз"),
02326 "la" => array("Latin", "Latina"),
02327 "lb" => array("Luxembourgish"),
02328 "lg" => array("Luganda"),
02329 "ln" => array("Lingala"),
02330 "lo" => array("Laothian"),
02331 "lt" => array("Lithuanian", "Lietuvių"),
02332 "lv" => array("Latvian", "Latviešu"),
02333 "mg" => array("Malagasy"),
02334 "mh" => array("Marshallese"),
02335 "mi" => array("Maori"),
02336 "mk" => array("Macedonian", "Македонски"),
02337 "ml" => array("Malayalam", "മലയാളം"),
02338 "mn" => array("Mongolian"),
02339 "mo" => array("Moldavian"),
02340 "mr" => array("Marathi"),
02341 "ms" => array("Malay", "Bahasa Melayu"),
02342 "mt" => array("Maltese", "Malti"),
02343 "my" => array("Burmese"),
02344 "na" => array("Nauru"),
02345 "nd" => array("North Ndebele"),
02346 "ne" => array("Nepali"),
02347 "ng" => array("Ndonga"),
02348 "nl" => array("Dutch", "Nederlands"),
02349 "nb" => array("Norwegian Bokmål", "Bokmål"),
02350 "nn" => array("Norwegian Nynorsk", "Nynorsk"),
02351 "nr" => array("South Ndebele"),
02352 "nv" => array("Navajo"),
02353 "ny" => array("Chichewa"),
02354 "oc" => array("Occitan"),
02355 "om" => array("Oromo"),
02356 "or" => array("Oriya"),
02357 "os" => array("Ossetian"),
02358 "pa" => array("Punjabi"),
02359 "pi" => array("Pali"),
02360 "pl" => array("Polish", "Polski"),
02361 "ps" => array("Pashto", "پښتو", LANGUAGE_RTL),
02362 "pt" => array("Portuguese, Portugal", "Português"),
02363 "pt-br" => array("Portuguese, Brazil", "Português"),
02364 "qu" => array("Quechua"),
02365 "rm" => array("Rhaeto-Romance"),
02366 "rn" => array("Kirundi"),
02367 "ro" => array("Romanian", "Română"),
02368 "ru" => array("Russian", "Русский"),
02369 "rw" => array("Kinyarwanda"),
02370 "sa" => array("Sanskrit"),
02371 "sc" => array("Sardinian"),
02372 "sd" => array("Sindhi"),
02373 "se" => array("Northern Sami"),
02374 "sg" => array("Sango"),
02375 "sh" => array("Serbo-Croatian"),
02376 "si" => array("Singhalese"),
02377 "sk" => array("Slovak", "Slovenčina"),
02378 "sl" => array("Slovenian", "Slovenščina"),
02379 "sm" => array("Samoan"),
02380 "sn" => array("Shona"),
02381 "so" => array("Somali"),
02382 "sq" => array("Albanian", "Shqip"),
02383 "sr" => array("Serbian", "Српски"),
02384 "ss" => array("Siswati"),
02385 "st" => array("Sesotho"),
02386 "su" => array("Sudanese"),
02387 "sv" => array("Swedish", "Svenska"),
02388 "sw" => array("Swahili", "Kiswahili"),
02389 "ta" => array("Tamil", "தமிழ்"),
02390 "te" => array("Telugu", "తెలుగు"),
02391 "tg" => array("Tajik"),
02392 "th" => array("Thai", "ภาษาไทย"),
02393 "ti" => array("Tigrinya"),
02394 "tk" => array("Turkmen"),
02395 "tl" => array("Tagalog"),
02396 "tn" => array("Setswana"),
02397 "to" => array("Tonga"),
02398 "tr" => array("Turkish", "Türkçe"),
02399 "ts" => array("Tsonga"),
02400 "tt" => array("Tatar", "Tatarça"),
02401 "tw" => array("Twi"),
02402 "ty" => array("Tahitian"),
02403 "ug" => array("Uighur"),
02404 "uk" => array("Ukrainian", "Українська"),
02405 "ur" => array("Urdu", "اردو", LANGUAGE_RTL),
02406 "uz" => array("Uzbek", "o'zbek"),
02407 "ve" => array("Venda"),
02408 "vi" => array("Vietnamese", "Tiếng Việt"),
02409 "wo" => array("Wolof"),
02410 "xh" => array("Xhosa", "isiXhosa"),
02411 "yi" => array("Yiddish"),
02412 "yo" => array("Yoruba", "Yorùbá"),
02413 "za" => array("Zhuang"),
02414 "zh-hans" => array("Chinese, Simplified", "简体中文"),
02415 "zh-hant" => array("Chinese, Traditional", "繁體中文"),
02416 "zu" => array("Zulu", "isiZulu"),
02417 );
02418 }
02442 function locale_batch_by_language($langcode, $finished = NULL, $skip = array()) {
02443
02444 $files = array();
02445 $components = array();
02446 $query = "SELECT name, filename FROM {system} WHERE status = 1";
02447 if (count($skip)) {
02448 $query .= " AND name NOT IN (" . db_placeholders($skip, 'varchar') . ")";
02449 }
02450 $result = db_query($query, $skip);
02451 while ($component = db_fetch_object($result)) {
02452
02453
02454
02455
02456 $files = array_merge($files, file_scan_directory(dirname($component->filename) . '/translations', '(^|\.)' . $langcode . '\.po$', array('.', '..', 'CVS'), 0, FALSE));
02457 $components[] = $component->name;
02458 }
02459
02460 return _locale_batch_build($files, $finished, $components);
02461 }
02462
02474 function locale_batch_by_component($components, $finished = '_locale_batch_system_finished') {
02475 $files = array();
02476 $languages = language_list('enabled');
02477 unset($languages[1]['en']);
02478 if (count($languages[1])) {
02479 $language_list = join('|', array_keys($languages[1]));
02480
02481 $result = db_query("SELECT name, filename FROM {system} WHERE status = 1");
02482 while ($component = db_fetch_object($result)) {
02483 if (in_array($component->name, $components)) {
02484
02485
02486
02487
02488 $files = array_merge($files, file_scan_directory(dirname($component->filename) . '/translations', '(^|\.)(' . $language_list . ')\.po$', array('.', '..', 'CVS'), 0, FALSE));
02489 }
02490 }
02491 return _locale_batch_build($files, $finished);
02492 }
02493 return FALSE;
02494 }
02495
02508 function _locale_batch_build($files, $finished = NULL, $components = array()) {
02509 $t = get_t();
02510 if (count($files)) {
02511 $operations = array();
02512 foreach ($files as $file) {
02513
02514 $operations[] = array('_locale_batch_import', array($file->filename)); }
02515 $batch = array(
02516 'operations' => $operations,
02517 'title' => $t('Importing interface translations'),
02518 'init_message' => $t('Starting import'),
02519 'error_message' => $t('Error importing interface translations'),
02520 'file' => './includes/locale.inc',
02521
02522
02523 '#components' => $components,
02524 );
02525 if (isset($finished)) {
02526 $batch['finished'] = $finished;
02527 }
02528 return $batch;
02529 }
02530 return FALSE;
02531 }
02532
02541 function _locale_batch_import($filepath, &$context) {
02542
02543
02544 if (preg_match('!(/|\.)([^\./]+)\.po$!', $filepath, $langcode)) {
02545 $file = (object) array('filename' => basename($filepath), 'filepath' => $filepath);
02546 _locale_import_read_po('db-store', $file, LOCALE_IMPORT_KEEP, $langcode[2]);
02547 $context['results'][] = $filepath;
02548 }
02549 }
02550
02555 function _locale_batch_system_finished($success, $results) {
02556 if ($success) {
02557 drupal_set_message(format_plural(count($results), 'One translation file imported for the newly installed modules.', '@count translation files imported for the newly installed modules.'));
02558 }
02559 }
02560
02565 function _locale_batch_language_finished($success, $results) {
02566 if ($success) {
02567 drupal_set_message(format_plural(count($results), 'One translation file imported for the enabled modules.', '@count translation files imported for the enabled modules.'));
02568 }
02569 }
02570