2004-08-11 11:26:20 +00:00
< ? php
// $Id$
2004-08-21 06:42:38 +00:00
2004-08-11 11:26:20 +00:00
/**
* @ file
2008-05-26 17:12:55 +00:00
* Administration functions for locale . module .
2004-08-11 11:26:20 +00:00
*/
2008-05-26 17:12:55 +00:00
/**
* Regular expression pattern used to localize JavaScript strings .
*/
2007-06-08 12:51:59 +00:00
define ( 'LOCALE_JS_STRING' , '(?:(?:\'(?:\\\\\'|[^\'])*\'|"(?:\\\\"|[^"])*")(?:\s*\+\s*)?)+' );
2007-06-17 17:41:40 +00:00
/**
* Translation import mode overwriting all existing translations
* if new translated version available .
*/
define ( 'LOCALE_IMPORT_OVERWRITE' , 0 );
/**
* Translation import mode keeping existing translations and only
* inserting new strings .
*/
define ( 'LOCALE_IMPORT_KEEP' , 1 );
2004-08-11 11:26:20 +00:00
/**
2007-05-03 09:51:08 +00:00
* @ defgroup locale - language - overview Language overview functionality
* @ {
2004-08-11 11:26:20 +00:00
*/
/**
2007-05-03 09:51:08 +00:00
* User interface for the language overview screen .
2004-08-11 11:26:20 +00:00
*/
2007-05-03 09:51:08 +00:00
function locale_languages_overview_form () {
2007-03-26 01:32:22 +00:00
$languages = language_list ( 'language' , TRUE );
2004-08-11 11:26:20 +00:00
2005-10-07 06:11:12 +00:00
$options = array ();
2007-03-26 01:32:22 +00:00
$form [ 'weight' ] = array ( '#tree' => TRUE );
foreach ( $languages as $langcode => $language ) {
2004-08-12 18:00:11 +00:00
2007-03-26 01:32:22 +00:00
$options [ $langcode ] = '' ;
if ( $language -> enabled ) {
$enabled [] = $langcode ;
2004-08-11 11:26:20 +00:00
}
2007-03-26 01:32:22 +00:00
$form [ 'weight' ][ $langcode ] = array (
'#type' => 'weight' ,
'#default_value' => $language -> weight
);
2008-07-16 21:59:29 +00:00
$form [ 'name' ][ $langcode ] = array ( '#markup' => check_plain ( $language -> name ));
$form [ 'native' ][ $langcode ] = array ( '#markup' => check_plain ( $language -> native ));
$form [ 'direction' ][ $langcode ] = array ( '#markup' => ( $language -> direction == LANGUAGE_RTL ? t ( 'Right to left' ) : t ( 'Left to right' )));
2004-08-11 11:26:20 +00:00
}
2006-03-17 18:35:56 +00:00
$form [ 'enabled' ] = array ( '#type' => 'checkboxes' ,
'#options' => $options ,
'#default_value' => $enabled ,
);
$form [ 'site_default' ] = array ( '#type' => 'radios' ,
'#options' => $options ,
2007-05-29 14:37:49 +00:00
'#default_value' => language_default ( 'language' ),
2006-03-17 18:35:56 +00:00
);
2005-10-11 19:44:35 +00:00
$form [ 'submit' ] = array ( '#type' => 'submit' , '#value' => t ( 'Save configuration' ));
2007-05-03 09:51:08 +00:00
$form [ '#theme' ] = 'locale_languages_overview_form' ;
2005-10-07 06:51:43 +00:00
2006-08-18 18:58:47 +00:00
return $form ;
2005-10-07 06:11:12 +00:00
}
2004-08-12 18:00:11 +00:00
2006-03-17 18:35:56 +00:00
/**
2007-07-02 14:41:37 +00:00
* Theme the language overview form .
2007-12-06 09:58:34 +00:00
*
* @ ingroup themeable
2006-03-17 18:35:56 +00:00
*/
2007-05-03 09:51:08 +00:00
function theme_locale_languages_overview_form ( $form ) {
2007-04-09 14:46:55 +00:00
$default = language_default ();
2005-10-07 06:11:12 +00:00
foreach ( $form [ 'name' ] as $key => $element ) {
2006-03-17 18:35:56 +00:00
// Do not take form control structures.
2005-10-07 06:11:12 +00:00
if ( is_array ( $element ) && element_child ( $key )) {
2007-05-21 20:21:39 +00:00
// Disable checkbox for the default language, because it cannot be disabled.
if ( $key == $default -> language ) {
2007-11-26 23:33:03 +00:00
$form [ 'enabled' ][ $key ][ '#attributes' ][ 'disabled' ] = 'disabled' ;
2007-05-21 20:21:39 +00:00
}
$rows [] = array (
array ( 'data' => drupal_render ( $form [ 'enabled' ][ $key ]), 'align' => 'center' ),
check_plain ( $key ),
2008-04-14 17:48:46 +00:00
'<strong>' . drupal_render ( $form [ 'name' ][ $key ]) . '</strong>' ,
2007-05-21 20:21:39 +00:00
drupal_render ( $form [ 'native' ][ $key ]),
drupal_render ( $form [ 'direction' ][ $key ]),
drupal_render ( $form [ 'site_default' ][ $key ]),
drupal_render ( $form [ 'weight' ][ $key ]),
2008-04-14 17:48:46 +00:00
l ( t ( 'edit' ), 'admin/settings/language/edit/' . $key ) . (( $key != 'en' && $key != $default -> language ) ? ' ' . l ( t ( 'delete' ), 'admin/settings/language/delete/' . $key ) : '' )
2007-05-21 20:21:39 +00:00
);
2005-10-07 06:11:12 +00:00
}
}
2007-03-26 01:32:22 +00:00
$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' )));
2005-10-07 06:11:12 +00:00
$output = theme ( 'table' , $header , $rows );
2006-08-10 15:42:33 +00:00
$output .= drupal_render ( $form );
2006-04-17 20:48:26 +00:00
2005-10-07 06:11:12 +00:00
return $output ;
2004-08-11 11:26:20 +00:00
}
/**
2007-05-03 09:51:08 +00:00
* Process language overview form submissions , updating existing languages .
2004-08-11 11:26:20 +00:00
*/
2007-06-04 07:22:23 +00:00
function locale_languages_overview_form_submit ( $form , & $form_state ) {
2007-03-26 01:32:22 +00:00
$languages = language_list ();
2007-08-20 07:54:46 +00:00
$default = language_default ();
2007-03-26 01:32:22 +00:00
$enabled_count = 0 ;
foreach ( $languages as $langcode => $language ) {
2007-08-20 07:54:46 +00:00
if ( $form_state [ 'values' ][ 'site_default' ] == $langcode || $default -> language == $langcode ) {
// Automatically enable the default language and the language
// which was default previously (because we will not get the
// value from that disabled checkox).
2007-06-04 07:22:23 +00:00
$form_state [ 'values' ][ 'enabled' ][ $langcode ] = 1 ;
2006-03-17 18:35:56 +00:00
}
2007-06-04 07:22:23 +00:00
if ( $form_state [ 'values' ][ 'enabled' ][ $langcode ]) {
2007-03-26 01:32:22 +00:00
$enabled_count ++ ;
$language -> enabled = 1 ;
2006-03-17 18:35:56 +00:00
}
else {
2007-03-26 01:32:22 +00:00
$language -> enabled = 0 ;
2006-03-17 18:35:56 +00:00
}
2007-06-04 07:22:23 +00:00
$language -> weight = $form_state [ 'values' ][ 'weight' ][ $langcode ];
2007-03-26 01:32:22 +00:00
db_query ( " UPDATE { languages} SET enabled = %d, weight = %d WHERE language = '%s' " , $language -> enabled , $language -> weight , $langcode );
$languages [ $langcode ] = $language ;
2006-03-17 18:35:56 +00:00
}
drupal_set_message ( t ( 'Configuration saved.' ));
2007-06-04 07:22:23 +00:00
variable_set ( 'language_default' , $languages [ $form_state [ 'values' ][ 'site_default' ]]);
2007-03-26 01:32:22 +00:00
variable_set ( 'language_count' , $enabled_count );
2006-04-17 20:48:26 +00:00
2007-03-26 01:32:22 +00:00
// Changing the language settings impacts the interface.
2006-08-30 08:46:17 +00:00
cache_clear_all ( '*' , 'cache_page' , TRUE );
2004-08-12 18:00:11 +00:00
2007-05-14 13:43:38 +00:00
$form_state [ 'redirect' ] = 'admin/settings/language' ;
return ;
2007-05-03 09:51:08 +00:00
}
/**
* @ } End of " locale-language-overview "
*/
/**
* @ defgroup locale - language - add - edit Language addition and editing functionality
* @ {
*/
/**
* User interface for the language addition screen .
*/
function locale_languages_add_screen () {
$output = drupal_get_form ( 'locale_languages_predefined_form' );
$output .= drupal_get_form ( 'locale_languages_custom_form' );
return $output ;
2006-03-17 18:35:56 +00:00
}
2007-03-26 01:32:22 +00:00
/**
* Predefined language setup form .
*/
2007-05-03 09:51:08 +00:00
function locale_languages_predefined_form () {
2007-03-26 01:32:22 +00:00
$predefined = _locale_prepare_predefined_list ();
2005-10-07 06:11:12 +00:00
$form = array ();
2006-03-17 18:35:56 +00:00
$form [ 'language list' ] = array ( '#type' => 'fieldset' ,
2007-03-26 01:32:22 +00:00
'#title' => t ( 'Predefined language' ),
2006-03-17 18:35:56 +00:00
'#collapsible' => TRUE ,
);
$form [ 'language list' ][ 'langcode' ] = array ( '#type' => 'select' ,
'#title' => t ( 'Language name' ),
2007-03-26 01:32:22 +00:00
'#default_value' => key ( $predefined ),
'#options' => $predefined ,
2007-12-18 16:27:44 +00:00
'#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.)' ),
2006-03-17 18:35:56 +00:00
);
$form [ 'language list' ][ 'submit' ] = array ( '#type' => 'submit' , '#value' => t ( 'Add language' ));
2006-08-18 18:58:47 +00:00
return $form ;
}
2006-04-17 20:48:26 +00:00
2007-03-26 01:32:22 +00:00
/**
* Custom language addition form .
*/
2007-05-03 09:51:08 +00:00
function locale_languages_custom_form () {
2005-10-07 06:11:12 +00:00
$form = array ();
2006-03-17 18:35:56 +00:00
$form [ 'custom language' ] = array ( '#type' => 'fieldset' ,
'#title' => t ( 'Custom language' ),
'#collapsible' => TRUE ,
2007-05-05 08:55:15 +00:00
'#collapsed' => TRUE ,
2006-03-17 18:35:56 +00:00
);
2007-05-03 09:51:08 +00:00
_locale_languages_common_controls ( $form [ 'custom language' ]);
2007-03-26 01:32:22 +00:00
$form [ 'custom language' ][ 'submit' ] = array (
'#type' => 'submit' ,
'#value' => t ( 'Add custom language' )
2006-03-17 18:35:56 +00:00
);
2007-05-03 09:51:08 +00:00
// Reuse the validation and submit functions of the predefined language setup form.
2007-05-14 13:43:38 +00:00
$form [ '#submit' ][] = 'locale_languages_predefined_form_submit' ;
$form [ '#validate' ][] = 'locale_languages_predefined_form_validate' ;
2007-03-26 01:32:22 +00:00
return $form ;
}
/**
* Editing screen for a particular language .
*
* @ param $langcode
2007-03-28 14:08:23 +00:00
* Language code of the language to edit .
2007-03-26 01:32:22 +00:00
*/
2007-06-04 07:22:23 +00:00
function locale_languages_edit_form ( & $form_state , $langcode ) {
2007-03-26 01:32:22 +00:00
if ( $language = db_fetch_object ( db_query ( " SELECT * FROM { languages} WHERE language = '%s' " , $langcode ))) {
$form = array ();
2007-05-03 09:51:08 +00:00
_locale_languages_common_controls ( $form , $language );
2007-03-26 01:32:22 +00:00
$form [ 'submit' ] = array (
'#type' => 'submit' ,
'#value' => t ( 'Save language' )
);
2007-05-14 13:43:38 +00:00
$form [ '#submit' ][] = 'locale_languages_edit_form_submit' ;
$form [ '#validate' ][] = 'locale_languages_edit_form_validate' ;
2007-03-26 01:32:22 +00:00
return $form ;
}
else {
drupal_not_found ();
}
}
/**
2007-05-03 09:51:08 +00:00
* Common elements of the language addition and editing form .
2007-03-26 01:32:22 +00:00
*
* @ param $form
* A parent form item ( or empty array ) to add items below .
* @ param $language
* Language object to edit .
*/
2007-05-03 09:51:08 +00:00
function _locale_languages_common_controls ( & $form , $language = NULL ) {
2007-03-26 01:32:22 +00:00
if ( ! is_object ( $language )) {
$language = new stdClass ();
}
if ( isset ( $language -> language )) {
$form [ 'langcode_view' ] = array (
'#type' => 'item' ,
'#title' => t ( 'Language code' ),
2008-07-16 21:59:29 +00:00
'#markup' => $language -> language
2007-03-26 01:32:22 +00:00
);
$form [ 'langcode' ] = array (
'#type' => 'value' ,
'#value' => $language -> language
);
}
else {
$form [ 'langcode' ] = array ( '#type' => 'textfield' ,
'#title' => t ( 'Language code' ),
'#size' => 12 ,
'#maxlength' => 60 ,
'#required' => TRUE ,
'#default_value' => @ $language -> language ,
'#disabled' => ( isset ( $language -> language )),
2007-12-18 16:27:44 +00:00
'#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' )),
2007-03-26 01:32:22 +00:00
);
}
2007-03-28 14:08:23 +00:00
$form [ 'name' ] = array ( '#type' => 'textfield' ,
2006-03-17 18:35:56 +00:00
'#title' => t ( 'Language name in English' ),
'#maxlength' => 64 ,
2007-03-26 01:32:22 +00:00
'#default_value' => @ $language -> name ,
2006-03-17 18:35:56 +00:00
'#required' => TRUE ,
2007-12-18 16:27:44 +00:00
'#description' => t ( 'Name of the language in English. Will be available for translation in all languages.' ),
2006-03-17 18:35:56 +00:00
);
2007-03-28 14:08:23 +00:00
$form [ 'native' ] = array ( '#type' => 'textfield' ,
2007-03-26 01:32:22 +00:00
'#title' => t ( 'Native language name' ),
'#maxlength' => 64 ,
'#default_value' => @ $language -> native ,
'#required' => TRUE ,
'#description' => t ( 'Name of the language in the language being added.' ),
);
$form [ 'prefix' ] = array ( '#type' => 'textfield' ,
'#title' => t ( 'Path prefix' ),
'#maxlength' => 64 ,
'#default_value' => @ $language -> prefix ,
2007-12-18 16:27:44 +00:00
'#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>' )
2007-03-26 01:32:22 +00:00
);
$form [ 'domain' ] = array ( '#type' => 'textfield' ,
'#title' => t ( 'Language domain' ),
'#maxlength' => 64 ,
'#default_value' => @ $language -> domain ,
2007-12-18 16:27:44 +00:00
'#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>' ),
2007-03-26 01:32:22 +00:00
);
$form [ 'direction' ] = array ( '#type' => 'radios' ,
'#title' => t ( 'Direction' ),
'#required' => TRUE ,
2007-12-18 16:27:44 +00:00
'#description' => t ( 'Direction that text in this language is presented.' ),
2007-03-26 01:32:22 +00:00
'#default_value' => @ $language -> direction ,
2007-05-03 09:51:08 +00:00
'#options' => array ( LANGUAGE_LTR => t ( 'Left to right' ), LANGUAGE_RTL => t ( 'Right to left' ))
2007-03-26 01:32:22 +00:00
);
2006-08-18 18:58:47 +00:00
return $form ;
}
2004-08-11 11:26:20 +00:00
/**
2006-03-17 18:35:56 +00:00
* Validate the language addition form .
*/
2007-06-04 07:22:23 +00:00
function locale_languages_predefined_form_validate ( $form , & $form_state ) {
$langcode = $form_state [ 'values' ][ 'langcode' ];
2007-05-03 09:51:08 +00:00
2007-08-12 15:55:36 +00:00
if ( $duplicate = db_result ( db_query ( " SELECT COUNT(*) FROM { languages} WHERE language = '%s' " , $langcode )) != 0 ) {
2007-06-04 07:22:23 +00:00
form_set_error ( 'langcode' , t ( 'The language %language (%code) already exists.' , array ( '%language' => $form_state [ 'values' ][ 'name' ], '%code' => $langcode )));
2006-03-17 18:35:56 +00:00
}
2007-06-04 07:22:23 +00:00
if ( ! isset ( $form_state [ 'values' ][ 'name' ])) {
2007-03-26 01:32:22 +00:00
// Predefined language selection.
$predefined = _locale_get_predefined_list ();
2007-05-03 09:51:08 +00:00
if ( ! isset ( $predefined [ $langcode ])) {
2006-03-17 18:35:56 +00:00
form_set_error ( 'langcode' , t ( 'Invalid language code.' ));
}
}
2007-03-26 01:32:22 +00:00
else {
2007-05-03 09:51:08 +00:00
// Reuse the editing form validation routine if we add a custom language.
2007-08-09 10:12:14 +00:00
locale_languages_edit_form_validate ( $form , $form_state );
2007-03-26 01:32:22 +00:00
}
2006-03-17 18:35:56 +00:00
}
/**
* Process the language addition form submission .
*/
2007-06-04 07:22:23 +00:00
function locale_languages_predefined_form_submit ( $form , & $form_state ) {
$langcode = $form_state [ 'values' ][ 'langcode' ];
if ( isset ( $form_state [ 'values' ][ 'name' ])) {
2006-03-17 18:35:56 +00:00
// Custom language form.
2007-06-04 07:22:23 +00:00
locale_add_language ( $langcode , $form_state [ 'values' ][ 'name' ], $form_state [ 'values' ][ 'native' ], $form_state [ 'values' ][ 'direction' ], $form_state [ 'values' ][ 'domain' ], $form_state [ 'values' ][ 'prefix' ]);
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' ))));
2006-03-17 18:35:56 +00:00
}
else {
2007-03-26 01:32:22 +00:00
// Predefined language selection.
$predefined = _locale_get_predefined_list ();
2007-05-15 15:29:49 +00:00
locale_add_language ( $langcode );
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' ))));
2007-03-26 01:32:22 +00:00
}
2007-05-22 07:42:37 +00:00
// See if we have language files to import for the newly added
// language, collect and import them.
if ( $batch = locale_batch_by_language ( $langcode , '_locale_batch_language_finished' )) {
batch_set ( $batch );
}
2007-05-14 13:43:38 +00:00
$form_state [ 'redirect' ] = 'admin/settings/language' ;
return ;
2007-03-26 01:32:22 +00:00
}
/**
* Validate the language editing form . Reused for custom language addition too .
*/
2007-06-04 07:22:23 +00:00
function locale_languages_edit_form_validate ( $form , & $form_state ) {
if ( ! empty ( $form_state [ 'values' ][ 'domain' ]) && ! empty ( $form_state [ 'values' ][ 'prefix' ])) {
2007-03-26 01:32:22 +00:00
form_set_error ( 'prefix' , t ( 'Domain and path prefix values should not be set at the same time.' ));
}
2008-07-22 20:03:41 +00:00
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' ]))) {
2007-06-04 07:22:23 +00:00
form_set_error ( 'domain' , t ( 'The domain (%domain) is already tied to a language (%language).' , array ( '%domain' => $form_state [ 'values' ][ 'domain' ], '%language' => $duplicate -> language )));
2007-03-26 01:32:22 +00:00
}
2007-06-04 07:22:23 +00:00
if ( empty ( $form_state [ 'values' ][ 'prefix' ]) && language_default ( 'language' ) != $form_state [ 'values' ][ 'langcode' ] && empty ( $form_state [ 'values' ][ 'domain' ])) {
2007-03-26 01:32:22 +00:00
form_set_error ( 'prefix' , t ( 'Only the default language can have both the domain and prefix empty.' ));
}
2008-07-22 20:03:41 +00:00
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' ]))) {
2007-06-04 07:22:23 +00:00
form_set_error ( 'prefix' , t ( 'The prefix (%prefix) is already tied to a language (%language).' , array ( '%prefix' => $form_state [ 'values' ][ 'prefix' ], '%language' => $duplicate -> language )));
2007-03-26 01:32:22 +00:00
}
}
/**
* Process the language editing form submission .
*/
2007-06-04 07:22:23 +00:00
function locale_languages_edit_form_submit ( $form , & $form_state ) {
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' ]);
2007-03-26 01:32:22 +00:00
$default = language_default ();
2007-06-04 07:22:23 +00:00
if ( $default -> language == $form_state [ 'values' ][ 'langcode' ]) {
2007-03-28 14:08:23 +00:00
$properties = array ( 'name' , 'native' , 'direction' , 'enabled' , 'plurals' , 'formula' , 'domain' , 'prefix' , 'weight' );
2007-04-13 08:56:59 +00:00
foreach ( $properties as $keyname ) {
2007-07-21 09:26:07 +00:00
if ( isset ( $form_state [ 'values' ][ $keyname ])) {
$default -> $keyname = $form_state [ 'values' ][ $keyname ];
}
2007-03-28 14:08:23 +00:00
}
2007-03-26 01:32:22 +00:00
variable_set ( 'language_default' , $default );
2006-03-17 18:35:56 +00:00
}
2007-05-14 13:43:38 +00:00
$form_state [ 'redirect' ] = 'admin/settings/language' ;
return ;
2007-03-26 01:32:22 +00:00
}
2007-05-03 09:51:08 +00:00
/**
* @ } End of " locale-language-add-edit "
*/
/**
* @ defgroup locale - language - delete Language deletion functionality
* @ {
*/
/**
* User interface for the language deletion confirmation screen .
*/
2007-06-04 07:22:23 +00:00
function locale_languages_delete_form ( & $form_state , $langcode ) {
2007-05-03 09:51:08 +00:00
// Do not allow deletion of English locale.
if ( $langcode == 'en' ) {
drupal_set_message ( t ( 'The English language cannot be deleted.' ));
drupal_goto ( 'admin/settings/language' );
}
2007-05-29 14:37:49 +00:00
if ( language_default ( 'language' ) == $langcode ) {
2007-05-03 09:51:08 +00:00
drupal_set_message ( t ( 'The default language cannot be deleted.' ));
drupal_goto ( 'admin/settings/language' );
}
// For other languages, warn user that data loss is ahead.
$languages = language_list ();
if ( ! isset ( $languages [ $langcode ])) {
drupal_not_found ();
}
else {
$form [ 'langcode' ] = array ( '#type' => 'value' , '#value' => $langcode );
2007-07-01 17:41:16 +00:00
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' ));
2007-05-03 09:51:08 +00:00
}
}
/**
* Process language deletion submissions .
*/
2007-06-04 07:22:23 +00:00
function locale_languages_delete_form_submit ( $form , & $form_state ) {
2007-05-03 09:51:08 +00:00
$languages = language_list ();
2007-06-04 07:22:23 +00:00
if ( isset ( $languages [ $form_state [ 'values' ][ 'langcode' ]])) {
2007-11-26 22:34:09 +00:00
// Remove translations first.
2007-06-04 07:22:23 +00:00
db_query ( " DELETE FROM { locales_target} WHERE language = '%s' " , $form_state [ 'values' ][ 'langcode' ]);
2008-04-14 17:48:46 +00:00
cache_clear_all ( 'locale:' . $form_state [ 'values' ][ 'langcode' ], 'cache' );
2007-11-26 22:34:09 +00:00
// With no translations, this removes existing JavaScript translations file.
_locale_rebuild_js ( $form_state [ 'values' ][ 'langcode' ]);
// Remove the language.
db_query ( " DELETE FROM { languages} WHERE language = '%s' " , $form_state [ 'values' ][ 'langcode' ]);
2007-06-04 07:22:23 +00:00
db_query ( " UPDATE { node} SET language = '' WHERE language = '%s' " , $form_state [ 'values' ][ 'langcode' ]);
$variables = array ( '%locale' => $languages [ $form_state [ 'values' ][ 'langcode' ]] -> name );
2007-05-03 09:51:08 +00:00
drupal_set_message ( t ( 'The language %locale has been removed.' , $variables ));
watchdog ( 'locale' , 'The language %locale has been removed.' , $variables );
}
// Changing the language settings impacts the interface:
cache_clear_all ( '*' , 'cache_page' , TRUE );
2007-05-14 13:43:38 +00:00
$form_state [ 'redirect' ] = 'admin/settings/language' ;
return ;
2007-05-03 09:51:08 +00:00
}
/**
* @ } End of " locale-language-add-edit "
*/
/**
* @ defgroup locale - languages - negotiation Language negotiation options screen
* @ {
*/
2007-03-26 01:32:22 +00:00
/**
* Setting for language negotiation options
*/
2007-05-03 09:51:08 +00:00
function locale_languages_configure_form () {
2007-03-26 01:32:22 +00:00
$form [ 'language_negotiation' ] = array (
'#title' => t ( 'Language negotiation' ),
'#type' => 'radios' ,
'#options' => array (
2007-12-18 16:27:44 +00:00
LANGUAGE_NEGOTIATION_NONE => t ( 'None.' ),
LANGUAGE_NEGOTIATION_PATH_DEFAULT => t ( 'Path prefix only.' ),
LANGUAGE_NEGOTIATION_PATH => t ( 'Path prefix with language fallback.' ),
LANGUAGE_NEGOTIATION_DOMAIN => t ( 'Domain name only.' )),
2007-03-26 01:32:22 +00:00
'#default_value' => variable_get ( 'language_negotiation' , LANGUAGE_NEGOTIATION_NONE ),
2007-12-18 16:27:44 +00:00
'#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> " )
2007-03-26 01:32:22 +00:00
);
$form [ 'submit' ] = array (
'#type' => 'submit' ,
'#value' => t ( 'Save settings' )
);
return $form ;
}
2006-04-17 20:48:26 +00:00
2007-03-26 01:32:22 +00:00
/**
* Submit function for language negotiation settings .
*/
2007-06-04 07:22:23 +00:00
function locale_languages_configure_form_submit ( $form , & $form_state ) {
variable_set ( 'language_negotiation' , $form_state [ 'values' ][ 'language_negotiation' ]);
2007-03-26 01:32:22 +00:00
drupal_set_message ( t ( 'Language negotiation configuration saved.' ));
2007-05-14 13:43:38 +00:00
$form_state [ 'redirect' ] = 'admin/settings/language' ;
return ;
2007-05-03 09:51:08 +00:00
}
/**
* @ } End of " locale-languages-negotiation "
*/
/**
* @ defgroup locale - translate - overview Translation overview screen .
* @ {
*/
/**
* Overview screen for translations .
*/
function locale_translate_overview_screen () {
$languages = language_list ( 'language' , TRUE );
$groups = module_invoke_all ( 'locale' , 'groups' );
// Build headers with all groups in order.
$headers = array_merge ( array ( t ( 'Language' )), array_values ( $groups ));
// Collect summaries of all source strings in all groups.
$sums = db_query ( " SELECT COUNT(*) AS strings, textgroup FROM { locales_source} GROUP BY textgroup " );
$groupsums = array ();
while ( $group = db_fetch_object ( $sums )) {
$groupsums [ $group -> textgroup ] = $group -> strings ;
}
2007-11-26 16:36:44 +00:00
// Set up overview table with default values, ensuring common order for values.
2007-05-03 09:51:08 +00:00
$rows = array ();
foreach ( $languages as $langcode => $language ) {
$rows [ $langcode ] = array ( 'name' => ( $langcode == 'en' ? t ( 'English (built-in)' ) : t ( $language -> name )));
foreach ( $groups as $group => $name ) {
2008-04-14 17:48:46 +00:00
$rows [ $langcode ][ $group ] = ( $langcode == 'en' ? t ( 'n/a' ) : '0/' . ( isset ( $groupsums [ $group ]) ? $groupsums [ $group ] : 0 ) . ' (0%)' );
2007-05-03 09:51:08 +00:00
}
}
// Languages with at least one record in the locale table.
2007-09-01 12:50:47 +00:00
$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 " );
2007-05-03 09:51:08 +00:00
while ( $data = db_fetch_object ( $translations )) {
$ratio = ( ! empty ( $groupsums [ $data -> textgroup ]) && $data -> translation > 0 ) ? round (( $data -> translation / $groupsums [ $data -> textgroup ]) * 100. , 2 ) : 0 ;
2008-04-14 17:48:46 +00:00
$rows [ $data -> language ][ $data -> textgroup ] = $data -> translation . '/' . $groupsums [ $data -> textgroup ] . " ( $ratio %) " ;
2007-05-03 09:51:08 +00:00
}
return theme ( 'table' , $headers , $rows );
}
/**
* @ } End of " locale-translate-overview "
*/
/**
* @ defgroup locale - translate - seek Translation search screen .
* @ {
*/
/**
* String search screen .
*/
function locale_translate_seek_screen () {
$output = _locale_translate_seek ();
$output .= drupal_get_form ( 'locale_translate_seek_form' );
return $output ;
}
/**
* User interface for the string search screen .
*/
function locale_translate_seek_form () {
// Get all languages, except English
$languages = locale_language_list ( 'name' , TRUE );
unset ( $languages [ 'en' ]);
// Present edit form preserving previous user settings
$query = _locale_translate_seek_query ();
$form = array ();
$form [ 'search' ] = array ( '#type' => 'fieldset' ,
'#title' => t ( 'Search' ),
);
$form [ 'search' ][ 'string' ] = array ( '#type' => 'textfield' ,
'#title' => t ( 'String contains' ),
'#default_value' => @ $query [ 'string' ],
'#description' => t ( 'Leave blank to show all strings. The search is case sensitive.' ),
);
2008-01-02 12:04:17 +00:00
$form [ 'search' ][ 'language' ] = array (
2008-01-02 22:49:43 +00:00
// Change type of form widget if more the 5 options will
// be present (2 of the options are added below).
'#type' => ( count ( $languages ) <= 3 ? 'radios' : 'select' ),
2007-05-03 09:51:08 +00:00
'#title' => t ( 'Language' ),
'#default_value' => ( ! empty ( $query [ 'language' ]) ? $query [ 'language' ] : 'all' ),
'#options' => array_merge ( array ( 'all' => t ( 'All languages' ), 'en' => t ( 'English (provided by Drupal)' )), $languages ),
);
$form [ 'search' ][ 'translation' ] = array ( '#type' => 'radios' ,
'#title' => t ( 'Search in' ),
'#default_value' => ( ! empty ( $query [ 'translation' ]) ? $query [ 'translation' ] : 'all' ),
2007-09-01 12:50:47 +00:00
'#options' => array ( 'all' => t ( 'Both translated and untranslated strings' ), 'translated' => t ( 'Only translated strings' ), 'untranslated' => t ( 'Only untranslated strings' )),
2007-05-03 09:51:08 +00:00
);
$groups = module_invoke_all ( 'locale' , 'groups' );
$form [ 'search' ][ 'group' ] = array ( '#type' => 'radios' ,
'#title' => t ( 'Limit search to' ),
'#default_value' => ( ! empty ( $query [ 'group' ]) ? $query [ 'group' ] : 'all' ),
'#options' => array_merge ( array ( 'all' => t ( 'All text groups' )), $groups ),
);
$form [ 'search' ][ 'submit' ] = array ( '#type' => 'submit' , '#value' => t ( 'Search' ));
$form [ '#redirect' ] = FALSE ;
return $form ;
2006-03-17 18:35:56 +00:00
}
2007-05-03 09:51:08 +00:00
/**
* @ } End of " locale-translate-seek "
*/
2006-03-17 18:35:56 +00:00
2007-05-03 09:51:08 +00:00
/**
* @ defgroup locale - translate - import Translation import screen .
* @ {
*/
2007-03-26 01:32:22 +00:00
2006-03-17 18:35:56 +00:00
/**
* User interface for the translation import screen .
2004-08-11 11:26:20 +00:00
*/
2007-05-03 09:51:08 +00:00
function locale_translate_import_form () {
// Get all languages, except English
2007-03-28 14:08:23 +00:00
$names = locale_language_list ( 'name' , TRUE );
unset ( $names [ 'en' ]);
2004-08-12 18:00:11 +00:00
2007-03-28 14:08:23 +00:00
if ( ! count ( $names )) {
2007-03-26 01:32:22 +00:00
$languages = _locale_prepare_predefined_list ();
2007-03-28 14:08:23 +00:00
$default = array_shift ( array_keys ( $languages ));
2004-08-11 11:26:20 +00:00
}
else {
$languages = array (
2007-03-28 14:08:23 +00:00
t ( 'Already added languages' ) => $names ,
2007-03-26 01:32:22 +00:00
t ( 'Languages not yet added' ) => _locale_prepare_predefined_list ()
2004-08-11 11:26:20 +00:00
);
2007-03-28 14:08:23 +00:00
$default = array_shift ( array_keys ( $names ));
2004-08-11 11:26:20 +00:00
}
2004-08-21 21:13:29 +00:00
2005-10-07 06:11:12 +00:00
$form = array ();
2006-03-17 18:35:56 +00:00
$form [ 'import' ] = array ( '#type' => 'fieldset' ,
2006-04-30 00:28:53 +00:00
'#title' => t ( 'Import translation' ),
2006-03-17 18:35:56 +00:00
);
$form [ 'import' ][ 'file' ] = array ( '#type' => 'file' ,
'#title' => t ( 'Language file' ),
'#size' => 50 ,
2007-12-18 16:27:44 +00:00
'#description' => t ( 'A Gettext Portable Object (<em>.po</em>) file.' ),
2006-03-17 18:35:56 +00:00
);
$form [ 'import' ][ 'langcode' ] = array ( '#type' => 'select' ,
'#title' => t ( 'Import into' ),
2007-03-28 14:08:23 +00:00
'#options' => $languages ,
'#default_value' => $default ,
2007-05-03 09:51:08 +00:00
'#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.' ),
);
$form [ 'import' ][ 'group' ] = array ( '#type' => 'radios' ,
'#title' => t ( 'Text group' ),
'#default_value' => 'default' ,
'#options' => module_invoke_all ( 'locale' , 'groups' ),
'#description' => t ( 'Imported translations will be added to this text group.' ),
2006-03-17 18:35:56 +00:00
);
$form [ 'import' ][ 'mode' ] = array ( '#type' => 'radios' ,
'#title' => t ( 'Mode' ),
2008-01-02 13:27:26 +00:00
'#default_value' => LOCALE_IMPORT_KEEP ,
'#options' => array (
LOCALE_IMPORT_OVERWRITE => t ( 'Strings in the uploaded file replace existing ones, new ones are added' ),
LOCALE_IMPORT_KEEP => t ( 'Existing strings are kept, only new strings are added' )
),
2006-03-17 18:35:56 +00:00
);
$form [ 'import' ][ 'submit' ] = array ( '#type' => 'submit' , '#value' => t ( 'Import' ));
2005-10-11 19:44:35 +00:00
$form [ '#attributes' ][ 'enctype' ] = 'multipart/form-data' ;
2005-10-07 06:11:12 +00:00
2006-08-18 18:58:47 +00:00
return $form ;
2004-08-11 11:26:20 +00:00
}
2006-03-17 18:35:56 +00:00
/**
* Process the locale import form submission .
*/
2007-06-04 07:22:23 +00:00
function locale_translate_import_form_submit ( $form , & $form_state ) {
2007-03-28 14:08:23 +00:00
// Ensure we have the file uploaded
2007-05-30 08:08:59 +00:00
if ( $file = file_save_upload ( 'file' )) {
2007-03-28 14:08:23 +00:00
// Add language, if not yet supported
$languages = language_list ( 'language' , TRUE );
2007-06-04 07:22:23 +00:00
$langcode = $form_state [ 'values' ][ 'langcode' ];
2007-05-03 09:51:08 +00:00
if ( ! isset ( $languages [ $langcode ])) {
2007-03-28 14:08:23 +00:00
$predefined = _locale_get_predefined_list ();
2007-05-15 15:29:49 +00:00
locale_add_language ( $langcode );
drupal_set_message ( t ( 'The language %language has been created.' , array ( '%language' => t ( $predefined [ $langcode ][ 0 ]))));
2007-03-28 14:08:23 +00:00
}
2006-03-17 18:35:56 +00:00
2007-03-28 14:08:23 +00:00
// Now import strings into the language
2007-06-04 07:22:23 +00:00
if ( $ret = _locale_import_po ( $file , $langcode , $form_state [ 'values' ][ 'mode' ], $form_state [ 'values' ][ 'group' ]) == FALSE ) {
2007-04-24 13:53:15 +00:00
$variables = array ( '%filename' => $file -> filename );
drupal_set_message ( t ( 'The translation import of %filename failed.' , $variables ), 'error' );
watchdog ( 'locale' , 'The translation import of %filename failed.' , $variables , WATCHDOG_ERROR );
2007-03-28 14:08:23 +00:00
}
}
else {
drupal_set_message ( t ( 'File to import not found.' ), 'error' );
2007-05-03 09:51:08 +00:00
return 'admin/build/translate/import' ;
2006-03-17 18:35:56 +00:00
}
2007-05-14 13:43:38 +00:00
$form_state [ 'redirect' ] = 'admin/build/translate' ;
return ;
2007-05-03 09:51:08 +00:00
}
/**
* @ } End of " locale-translate-import "
*/
/**
* @ defgroup locale - translate - export Translation export screen .
* @ {
*/
/**
* User interface for the translation export screen .
*/
function locale_translate_export_screen () {
// Get all languages, except English
$names = locale_language_list ( 'name' , TRUE );
unset ( $names [ 'en' ]);
$output = '' ;
// Offer translation export if any language is set up.
if ( count ( $names )) {
$output = drupal_get_form ( 'locale_translate_export_po_form' , $names );
}
$output .= drupal_get_form ( 'locale_translate_export_pot_form' );
return $output ;
2006-03-17 18:35:56 +00:00
}
2007-05-03 09:51:08 +00:00
/**
* Form to export PO files for the languages provided .
*
* @ param $names
* An associate array with localized language names
*/
2007-06-04 07:22:23 +00:00
function locale_translate_export_po_form ( & $form_state , $names ) {
2006-08-18 18:58:47 +00:00
$form [ 'export' ] = array ( '#type' => 'fieldset' ,
'#title' => t ( 'Export translation' ),
'#collapsible' => TRUE ,
);
$form [ 'export' ][ 'langcode' ] = array ( '#type' => 'select' ,
'#title' => t ( 'Language name' ),
2007-03-28 14:08:23 +00:00
'#options' => $names ,
2007-12-18 16:27:44 +00:00
'#description' => t ( 'Select the language to export in Gettext Portable Object (<em>.po</em>) format.' ),
2006-08-18 18:58:47 +00:00
);
2007-05-03 09:51:08 +00:00
$form [ 'export' ][ 'group' ] = array ( '#type' => 'radios' ,
'#title' => t ( 'Text group' ),
'#default_value' => 'default' ,
'#options' => module_invoke_all ( 'locale' , 'groups' ),
);
2006-08-18 18:58:47 +00:00
$form [ 'export' ][ 'submit' ] = array ( '#type' => 'submit' , '#value' => t ( 'Export' ));
return $form ;
}
2007-05-03 09:51:08 +00:00
/**
* Translation template export form .
*/
function locale_translate_export_pot_form () {
2006-08-18 18:58:47 +00:00
// Complete template export of the strings
$form [ 'export' ] = array ( '#type' => 'fieldset' ,
'#title' => t ( 'Export template' ),
'#collapsible' => TRUE ,
2007-12-18 16:27:44 +00:00
'#description' => t ( 'Generate a Gettext Portable Object Template (<em>.pot</em>) file with all strings from the Drupal locale database.' ),
2007-05-03 09:51:08 +00:00
);
$form [ 'export' ][ 'group' ] = array ( '#type' => 'radios' ,
'#title' => t ( 'Text group' ),
'#default_value' => 'default' ,
'#options' => module_invoke_all ( 'locale' , 'groups' ),
2006-08-18 18:58:47 +00:00
);
$form [ 'export' ][ 'submit' ] = array ( '#type' => 'submit' , '#value' => t ( 'Export' ));
2007-05-03 09:51:08 +00:00
// Reuse PO export submission callback.
2007-05-14 13:43:38 +00:00
$form [ '#submit' ][] = 'locale_translate_export_po_form_submit' ;
$form [ '#validate' ][] = 'locale_translate_export_po_form_validate' ;
2006-08-18 18:58:47 +00:00
return $form ;
}
2006-03-17 18:35:56 +00:00
/**
2007-05-03 09:51:08 +00:00
* Process a translation ( or template ) export form submission .
2006-03-17 18:35:56 +00:00
*/
2007-06-04 07:22:23 +00:00
function locale_translate_export_po_form_submit ( $form , & $form_state ) {
2007-05-03 09:51:08 +00:00
// If template is required, language code is not given.
2007-06-23 20:45:36 +00:00
$language = NULL ;
if ( isset ( $form_state [ 'values' ][ 'langcode' ])) {
$languages = language_list ();
$language = $languages [ $form_state [ 'values' ][ 'langcode' ]];
}
_locale_export_po ( $language , _locale_export_po_generate ( $language , _locale_export_get_strings ( $language , $form_state [ 'values' ][ 'group' ])));
2006-03-17 18:35:56 +00:00
}
/**
2007-05-03 09:51:08 +00:00
* @ } End of " locale-translate-export "
2006-03-17 18:35:56 +00:00
*/
2007-03-26 01:32:22 +00:00
2006-03-17 18:35:56 +00:00
/**
2007-05-03 09:51:08 +00:00
* @ defgroup locale - translate - edit Translation text editing
* @ {
2006-03-17 18:35:56 +00:00
*/
/**
* User interface for string editing .
*/
2007-06-04 07:22:23 +00:00
function locale_translate_edit_form ( & $form_state , $lid ) {
2007-06-09 09:44:28 +00:00
// Fetch source string, if possible.
$source = db_fetch_object ( db_query ( 'SELECT source, textgroup, location FROM {locales_source} WHERE lid = %d' , $lid ));
if ( ! $source ) {
2007-05-03 09:51:08 +00:00
drupal_set_message ( t ( 'String not found.' ), 'error' );
drupal_goto ( 'admin/build/translate/search' );
2006-03-17 18:35:56 +00:00
}
2007-06-09 09:44:28 +00:00
// Add original text to the top and some values for form altering.
$form = array (
'original' => array (
'#type' => 'item' ,
'#title' => t ( 'Original text' ),
2008-07-16 21:59:29 +00:00
'#markup' => check_plain ( wordwrap ( $source -> source , 0 )),
2007-06-09 09:44:28 +00:00
),
'lid' => array (
'#type' => 'value' ,
'#value' => $lid
),
'textgroup' => array (
'#type' => 'value' ,
'#value' => $source -> textgroup ,
),
'location' => array (
'#type' => 'value' ,
'#value' => $source -> location
),
2006-03-17 18:35:56 +00:00
);
2007-06-09 09:44:28 +00:00
// Include default form controls with empty values for all languages.
// This ensures that the languages are always in the same order in forms.
$languages = language_list ();
$default = language_default ();
// We don't need the default language value, that value is in $source.
$omit = $source -> textgroup == 'default' ? 'en' : $default -> language ;
unset ( $languages [( $omit )]);
$form [ 'translations' ] = array ( '#tree' => TRUE );
// Approximate the number of rows to use in the default textarea.
$rows = min ( ceil ( str_word_count ( $source -> source ) / 12 ), 10 );
2007-03-26 01:32:22 +00:00
foreach ( $languages as $langcode => $language ) {
$form [ 'translations' ][ $langcode ] = array (
2006-05-16 09:22:36 +00:00
'#type' => 'textarea' ,
2007-03-26 01:32:22 +00:00
'#title' => t ( $language -> name ),
2006-03-17 18:35:56 +00:00
'#rows' => $rows ,
2007-06-09 09:44:28 +00:00
'#default_value' => '' ,
2006-03-17 18:35:56 +00:00
);
}
2007-06-11 15:21:14 +00:00
2007-06-09 09:44:28 +00:00
// Fetch translations and fill in default values in the form.
2008-07-22 20:03:41 +00:00
$result = db_query ( " SELECT DISTINCT translation, language FROM { locales_target} WHERE lid = %d AND language <> '%s' " , $lid , $omit );
2007-06-09 09:44:28 +00:00
while ( $translation = db_fetch_object ( $result )) {
$form [ 'translations' ][ $translation -> language ][ '#default_value' ] = $translation -> translation ;
}
2006-03-17 18:35:56 +00:00
$form [ 'submit' ] = array ( '#type' => 'submit' , '#value' => t ( 'Save translations' ));
2006-08-18 18:58:47 +00:00
return $form ;
2006-03-17 18:35:56 +00:00
}
/**
* Process string editing form submissions .
* Saves all translations of one string submitted from a form .
*/
2007-06-04 07:22:23 +00:00
function locale_translate_edit_form_submit ( $form , & $form_state ) {
$lid = $form_state [ 'values' ][ 'lid' ];
foreach ( $form_state [ 'values' ][ 'translations' ] as $key => $value ) {
2007-06-17 17:41:40 +00:00
$translation = db_result ( db_query ( " SELECT translation FROM { locales_target} WHERE lid = %d AND language = '%s' " , $lid , $key ));
if ( ! empty ( $value )) {
// Only update or insert if we have a value to use.
if ( ! empty ( $translation )) {
db_query ( " UPDATE { locales_target} SET translation = '%s' WHERE lid = %d AND language = '%s' " , $value , $lid , $key );
}
else {
db_query ( " INSERT INTO { locales_target} (lid, translation, language) VALUES (%d, '%s', '%s') " , $lid , $value , $key );
}
2006-03-17 18:35:56 +00:00
}
2007-06-17 17:41:40 +00:00
elseif ( ! empty ( $translation )) {
// Empty translation entered: remove existing entry from database.
db_query ( " DELETE FROM { locales_target} WHERE lid = %d AND language = '%s' " , $lid , $key );
2006-03-17 18:35:56 +00:00
}
2007-06-08 12:51:59 +00:00
2007-11-26 22:34:09 +00:00
// Force JavaScript translation file recreation for this language.
_locale_invalidate_js ( $key );
2006-03-17 18:35:56 +00:00
}
2007-06-08 12:51:59 +00:00
2006-03-17 18:35:56 +00:00
drupal_set_message ( t ( 'The string has been saved.' ));
2007-10-15 19:51:06 +00:00
// Clear locale cache.
cache_clear_all ( 'locale:' , 'cache' , TRUE );
2006-03-17 18:35:56 +00:00
2007-05-14 13:43:38 +00:00
$form_state [ 'redirect' ] = 'admin/build/translate/search' ;
return ;
2006-03-17 18:35:56 +00:00
}
2007-05-03 09:51:08 +00:00
/**
* @ } End of " locale-translate-edit "
*/
/**
* @ defgroup locale - translate - delete Translation delete interface .
* @ {
*/
2006-03-17 18:35:56 +00:00
/**
2008-08-05 18:11:44 +00:00
* String deletion confirmation page .
2006-03-17 18:35:56 +00:00
*/
2008-08-05 18:11:44 +00:00
function locale_translate_delete_page ( $lid ) {
if ( $source = db_fetch_object ( db_query ( 'SELECT * FROM {locales_source} WHERE lid = %d' , $lid ))) {
return drupal_get_form ( 'locale_translate_delete_form' , $source );
}
else {
return drupal_not_found ();
}
}
/**
* User interface for the string deletion confirmation screen .
*/
function locale_translate_delete_form ( & $form_state , $source ) {
$form [ 'lid' ] = array ( '#type' => 'value' , '#value' => $source -> lid );
return confirm_form ( $form , t ( 'Are you sure you want to delete the string "%source"?' , array ( '%source' => $source -> source )), 'admin/build/translate/search' , t ( 'Deleting the string will remove all translations of this string in all languages. This action cannot be undone.' ), t ( 'Delete' ), t ( 'Cancel' ));
}
/**
* Process string deletion submissions .
*/
function locale_translate_delete_form_submit ( $form , & $form_state ) {
db_query ( 'DELETE FROM {locales_source} WHERE lid = %d' , $form_state [ 'values' ][ 'lid' ]);
db_query ( 'DELETE FROM {locales_target} WHERE lid = %d' , $form_state [ 'values' ][ 'lid' ]);
2007-11-26 22:34:09 +00:00
// Force JavaScript translation file recreation for all languages.
_locale_invalidate_js ();
2007-10-15 19:51:06 +00:00
cache_clear_all ( 'locale:' , 'cache' , TRUE );
2006-03-17 18:35:56 +00:00
drupal_set_message ( t ( 'The string has been removed.' ));
2008-08-05 18:11:44 +00:00
$form_state [ 'redirect' ] = 'admin/build/translate/search' ;
2007-05-03 09:51:08 +00:00
}
/**
* @ } End of " locale-translate-delete "
*/
/**
* @ defgroup locale - api - add Language addition API .
* @ {
*/
/**
* API function to add a language .
*
* @ param $langcode
* Language code .
* @ param $name
* English name of the language
* @ param $native
* Native name of the language
* @ param $direction
* LANGUAGE_LTR or LANGUAGE_RTL
* @ param $domain
* Optional custom domain name with protocol , without
* trailing slash ( eg . http :// de . example . com ) .
* @ param $prefix
* Optional path prefix for the language . Defaults to the
* language code if omitted .
2007-05-15 15:29:49 +00:00
* @ param $enabled
* Optionally TRUE to enable the language when created or FALSE to disable .
* @ param $default
2007-07-02 14:41:37 +00:00
* Optionally set this language to be the default .
2007-05-03 09:51:08 +00:00
*/
2007-05-22 07:42:37 +00:00
function locale_add_language ( $langcode , $name = NULL , $native = NULL , $direction = LANGUAGE_LTR , $domain = '' , $prefix = '' , $enabled = TRUE , $default = FALSE ) {
2007-05-03 09:51:08 +00:00
// Default prefix on language code.
if ( empty ( $prefix )) {
2007-05-08 09:48:14 +00:00
$prefix = $langcode ;
2007-05-03 09:51:08 +00:00
}
2007-05-15 15:29:49 +00:00
// If name was not set, we add a predefined language.
if ( ! isset ( $name )) {
$predefined = _locale_get_predefined_list ();
$name = $predefined [ $langcode ][ 0 ];
$native = isset ( $predefined [ $langcode ][ 1 ]) ? $predefined [ $langcode ][ 1 ] : $predefined [ $langcode ][ 0 ];
2007-05-17 08:34:43 +00:00
$direction = isset ( $predefined [ $langcode ][ 2 ]) ? $predefined [ $langcode ][ 2 ] : LANGUAGE_LTR ;
2007-05-15 15:29:49 +00:00
}
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 );
2007-05-03 09:51:08 +00:00
2007-05-15 15:29:49 +00:00
// Only set it as default if enabled.
if ( $enabled && $default ) {
2007-11-11 16:14:45 +00:00
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' => '' ));
2007-05-03 09:51:08 +00:00
}
2007-08-20 07:54:46 +00:00
if ( $enabled ) {
// Increment enabled language count if we are adding an enabled language.
variable_set ( 'language_count' , variable_get ( 'language_count' , 1 ) + 1 );
}
2007-05-15 15:29:49 +00:00
2007-11-26 22:34:09 +00:00
// Force JavaScript translation file creation for the newly added language.
_locale_invalidate_js ( $langcode );
2007-05-03 09:51:08 +00:00
watchdog ( 'locale' , 'The %language language (%code) has been created.' , array ( '%language' => $name , '%code' => $langcode ));
2006-03-17 18:35:56 +00:00
}
2007-05-03 09:51:08 +00:00
/**
* @ } End of " locale-api-add "
*/
2006-03-17 18:35:56 +00:00
2007-05-03 09:51:08 +00:00
/**
* @ defgroup locale - api - import Translation import API .
* @ {
*/
2007-03-26 01:32:22 +00:00
2004-08-11 11:26:20 +00:00
/**
* Parses Gettext Portable Object file information and inserts into database
*
2006-09-01 05:38:40 +00:00
* @ param $file
* Drupal file object corresponding to the PO file to import
2007-06-08 12:51:59 +00:00
* @ param $langcode
2006-09-01 05:38:40 +00:00
* Language code
* @ param $mode
2007-06-17 17:41:40 +00:00
* Should existing translations be replaced LOCALE_IMPORT_KEEP or LOCALE_IMPORT_OVERWRITE
2007-05-03 09:51:08 +00:00
* @ param $group
* Text group to import PO file into ( eg . 'default' for interface translations )
2004-08-11 11:26:20 +00:00
*/
2007-06-08 12:51:59 +00:00
function _locale_import_po ( $file , $langcode , $mode , $group = NULL ) {
// If not in 'safe mode', increase the maximum execution time.
2004-08-21 21:13:29 +00:00
if ( ! ini_get ( 'safe_mode' )) {
set_time_limit ( 240 );
2004-09-08 15:38:26 +00:00
}
2004-08-21 21:13:29 +00:00
2007-06-08 12:51:59 +00:00
// Check if we have the language already in the database.
if ( ! db_fetch_object ( db_query ( " SELECT language FROM { languages} WHERE language = '%s' " , $langcode ))) {
2005-05-05 22:22:46 +00:00
drupal_set_message ( t ( 'The language selected for import is not supported.' ), 'error' );
2004-08-11 11:26:20 +00:00
return FALSE ;
}
2004-08-12 18:00:11 +00:00
2006-02-05 15:42:56 +00:00
// Get strings from file (returns on failure after a partial import, or on success)
2007-06-08 12:51:59 +00:00
$status = _locale_import_read_po ( 'db-store' , $file , $mode , $langcode , $group );
2006-06-22 12:23:39 +00:00
if ( $status === FALSE ) {
2007-06-08 12:51:59 +00:00
// Error messages are set in _locale_import_read_po().
2006-06-22 12:23:39 +00:00
return FALSE ;
}
2004-08-12 18:00:11 +00:00
2007-06-08 12:51:59 +00:00
// Get status information on import process.
2007-06-17 17:41:40 +00:00
list ( $headerdone , $additions , $updates , $deletes ) = _locale_import_one_string ( 'db-report' );
2004-08-12 18:00:11 +00:00
2006-02-05 15:42:56 +00:00
if ( ! $headerdone ) {
2006-08-18 12:17:00 +00:00
drupal_set_message ( t ( 'The translation file %filename appears to have a missing or malformed header.' , array ( '%filename' => $file -> filename )), 'error' );
2004-08-11 11:26:20 +00:00
}
2004-08-12 18:00:11 +00:00
2007-11-26 22:34:09 +00:00
// Clear cache and force refresh of JavaScript translations.
_locale_invalidate_js ( $langcode );
2007-10-15 19:51:06 +00:00
cache_clear_all ( 'locale:' , 'cache' , TRUE );
2004-10-06 12:18:03 +00:00
2007-06-08 12:51:59 +00:00
// Rebuild the menu, strings may have changed.
2004-10-05 20:09:47 +00:00
menu_rebuild ();
2004-10-06 12:18:03 +00:00
2007-06-17 17:41:40 +00:00
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 )));
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 ));
2004-08-11 11:26:20 +00:00
return TRUE ;
}
/**
* Parses Gettext Portable Object file into an array
*
2006-09-01 05:38:40 +00:00
* @ param $op
* Storage operation type : db - store or mem - store
* @ param $file
* Drupal file object corresponding to the PO file to import
* @ param $mode
2007-06-17 17:41:40 +00:00
* Should existing translations be replaced LOCALE_IMPORT_KEEP or LOCALE_IMPORT_OVERWRITE
2006-09-01 05:38:40 +00:00
* @ param $lang
* Language code
2007-05-03 09:51:08 +00:00
* @ param $group
* Text group to import PO file into ( eg . 'default' for interface translations )
2004-08-11 11:26:20 +00:00
*/
2007-11-22 23:58:34 +00:00
function _locale_import_read_po ( $op , $file , $mode = NULL , $lang = NULL , $group = 'default' ) {
2004-08-11 11:26:20 +00:00
2006-02-05 15:42:56 +00:00
$fd = fopen ( $file -> filepath , " rb " ); // File will get closed by PHP on return
2004-08-11 11:26:20 +00:00
if ( ! $fd ) {
2006-09-01 05:38:40 +00:00
_locale_import_message ( 'The translation import failed, because the file %filename could not be read.' , $file );
2004-08-11 11:26:20 +00:00
return FALSE ;
}
$context = " COMMENT " ; // Parser context: COMMENT, MSGID, MSGID_PLURAL, MSGSTR and MSGSTR_ARR
$current = array (); // Current entry being read
$plural = 0 ; // Current plural form
2006-02-05 15:42:56 +00:00
$lineno = 0 ; // Current line
2004-08-11 11:26:20 +00:00
2006-02-05 15:42:56 +00:00
while ( ! feof ( $fd )) {
$line = fgets ( $fd , 10 * 1024 ); // A line should not be this long
2007-11-21 18:24:37 +00:00
if ( $lineno == 0 ) {
2007-11-23 13:34:55 +00:00
// The first line might come with a UTF-8 BOM, which should be removed.
2007-11-21 18:24:37 +00:00
$line = str_replace ( " \xEF \xBB \xBF " , '' , $line );
}
2004-08-11 11:26:20 +00:00
$lineno ++ ;
2006-02-05 15:42:56 +00:00
$line = trim ( strtr ( $line , array ( " \\ \n " => " " )));
2004-08-11 11:26:20 +00:00
if ( ! strncmp ( " # " , $line , 1 )) { // A comment
if ( $context == " COMMENT " ) { // Already in comment context: add
$current [ " # " ][] = substr ( $line , 1 );
}
elseif (( $context == " MSGSTR " ) || ( $context == " MSGSTR_ARR " )) { // End current entry, start a new one
2007-11-21 22:04:37 +00:00
_locale_import_one_string ( $op , $current , $mode , $lang , $file , $group );
2004-08-11 11:26:20 +00:00
$current = array ();
$current [ " # " ][] = substr ( $line , 1 );
$context = " COMMENT " ;
}
else { // Parse error
2006-09-01 05:38:40 +00:00
_locale_import_message ( 'The translation file %filename contains an error: "msgstr" was expected but not found on line %line.' , $file , $lineno );
2004-08-11 11:26:20 +00:00
return FALSE ;
}
}
elseif ( ! strncmp ( " msgid_plural " , $line , 12 )) {
if ( $context != " MSGID " ) { // Must be plural form for current entry
2006-09-01 05:38:40 +00:00
_locale_import_message ( 'The translation file %filename contains an error: "msgid_plural" was expected but not found on line %line.' , $file , $lineno );
2004-08-11 11:26:20 +00:00
return FALSE ;
}
$line = trim ( substr ( $line , 12 ));
$quoted = _locale_import_parse_quoted ( $line );
2006-07-05 11:45:51 +00:00
if ( $quoted === FALSE ) {
2006-09-01 05:38:40 +00:00
_locale_import_message ( 'The translation file %filename contains a syntax error on line %line.' , $file , $lineno );
2004-08-11 11:26:20 +00:00
return FALSE ;
}
2008-04-14 17:48:46 +00:00
$current [ " msgid " ] = $current [ " msgid " ] . " \0 " . $quoted ;
2004-08-12 18:00:11 +00:00
$context = " MSGID_PLURAL " ;
2004-08-11 11:26:20 +00:00
}
elseif ( ! strncmp ( " msgid " , $line , 5 )) {
if ( $context == " MSGSTR " ) { // End current entry, start a new one
2007-11-21 22:04:37 +00:00
_locale_import_one_string ( $op , $current , $mode , $lang , $file , $group );
2004-08-11 11:26:20 +00:00
$current = array ();
}
elseif ( $context == " MSGID " ) { // Already in this context? Parse error
2006-09-01 05:38:40 +00:00
_locale_import_message ( 'The translation file %filename contains an error: "msgid" is unexpected on line %line.' , $file , $lineno );
2004-08-11 11:26:20 +00:00
return FALSE ;
}
$line = trim ( substr ( $line , 5 ));
$quoted = _locale_import_parse_quoted ( $line );
2006-07-05 11:45:51 +00:00
if ( $quoted === FALSE ) {
2007-12-22 23:24:26 +00:00
_locale_import_message ( 'The translation file %filename contains a syntax error on line %line.' , $file , $lineno );
2004-08-11 11:26:20 +00:00
return FALSE ;
}
$current [ " msgid " ] = $quoted ;
$context = " MSGID " ;
}
elseif ( ! strncmp ( " msgstr[ " , $line , 7 )) {
if (( $context != " MSGID " ) && ( $context != " MSGID_PLURAL " ) && ( $context != " MSGSTR_ARR " )) { // Must come after msgid, msgid_plural, or msgstr[]
2006-09-01 05:38:40 +00:00
_locale_import_message ( 'The translation file %filename contains an error: "msgstr[]" is unexpected on line %line.' , $file , $lineno );
2004-08-11 11:26:20 +00:00
return FALSE ;
}
2006-07-05 11:45:51 +00:00
if ( strpos ( $line , " ] " ) === FALSE ) {
2006-09-01 05:38:40 +00:00
_locale_import_message ( 'The translation file %filename contains a syntax error on line %line.' , $file , $lineno );
2004-08-11 11:26:20 +00:00
return FALSE ;
}
$frombracket = strstr ( $line , " [ " );
$plural = substr ( $frombracket , 1 , strpos ( $frombracket , " ] " ) - 1 );
$line = trim ( strstr ( $line , " " ));
$quoted = _locale_import_parse_quoted ( $line );
2006-07-05 11:45:51 +00:00
if ( $quoted === FALSE ) {
2006-09-01 05:38:40 +00:00
_locale_import_message ( 'The translation file %filename contains a syntax error on line %line.' , $file , $lineno );
2004-08-11 11:26:20 +00:00
return FALSE ;
}
$current [ " msgstr " ][ $plural ] = $quoted ;
$context = " MSGSTR_ARR " ;
}
elseif ( ! strncmp ( " msgstr " , $line , 6 )) {
if ( $context != " MSGID " ) { // Should come just after a msgid block
2006-09-01 05:38:40 +00:00
_locale_import_message ( 'The translation file %filename contains an error: "msgstr" is unexpected on line %line.' , $file , $lineno );
2004-08-11 11:26:20 +00:00
return FALSE ;
}
$line = trim ( substr ( $line , 6 ));
$quoted = _locale_import_parse_quoted ( $line );
2006-07-05 11:45:51 +00:00
if ( $quoted === FALSE ) {
2006-09-01 05:38:40 +00:00
_locale_import_message ( 'The translation file %filename contains a syntax error on line %line.' , $file , $lineno );
2004-08-11 11:26:20 +00:00
return FALSE ;
}
$current [ " msgstr " ] = $quoted ;
$context = " MSGSTR " ;
}
elseif ( $line != " " ) {
$quoted = _locale_import_parse_quoted ( $line );
2006-07-05 11:45:51 +00:00
if ( $quoted === FALSE ) {
2006-09-01 05:38:40 +00:00
_locale_import_message ( 'The translation file %filename contains a syntax error on line %line.' , $file , $lineno );
2004-08-11 11:26:20 +00:00
return FALSE ;
}
if (( $context == " MSGID " ) || ( $context == " MSGID_PLURAL " )) {
$current [ " msgid " ] .= $quoted ;
}
elseif ( $context == " MSGSTR " ) {
$current [ " msgstr " ] .= $quoted ;
}
elseif ( $context == " MSGSTR_ARR " ) {
$current [ " msgstr " ][ $plural ] .= $quoted ;
}
else {
2006-09-01 05:38:40 +00:00
_locale_import_message ( 'The translation file %filename contains an error: there is an unexpected string on line %line.' , $file , $lineno );
2004-08-11 11:26:20 +00:00
return FALSE ;
}
}
}
// End of PO file, flush last entry
if (( $context == " MSGSTR " ) || ( $context == " MSGSTR_ARR " )) {
2007-11-21 22:04:37 +00:00
_locale_import_one_string ( $op , $current , $mode , $lang , $file , $group );
2004-08-11 11:26:20 +00:00
}
elseif ( $context != " COMMENT " ) {
2006-09-01 05:38:40 +00:00
_locale_import_message ( 'The translation file %filename ended unexpectedly at line %line.' , $file , $lineno );
2004-08-11 11:26:20 +00:00
return FALSE ;
}
2006-02-05 15:42:56 +00:00
}
2006-09-01 05:38:40 +00:00
/**
2006-12-05 05:47:37 +00:00
* Sets an error message occurred during locale file parsing .
2006-09-01 05:38:40 +00:00
*
* @ param $message
* The message to be translated
* @ param $file
* Drupal file object corresponding to the PO file to import
* @ param $lineno
* An optional line number argument
*/
function _locale_import_message ( $message , $file , $lineno = NULL ) {
$vars = array ( '%filename' => $file -> filename );
if ( isset ( $lineno )) {
$vars [ '%line' ] = $lineno ;
}
2006-09-05 02:15:04 +00:00
$t = get_t ();
2006-09-01 05:38:40 +00:00
drupal_set_message ( $t ( $message , $vars ), 'error' );
}
2006-02-05 15:42:56 +00:00
/**
* Imports a string into the database
*
2006-09-01 05:38:40 +00:00
* @ param $op
* Operation to perform : 'db-store' , 'db-report' , 'mem-store' or 'mem-report'
* @ param $value
* Details of the string stored
* @ param $mode
2007-06-17 17:41:40 +00:00
* Should existing translations be replaced LOCALE_IMPORT_KEEP or LOCALE_IMPORT_OVERWRITE
2006-09-01 05:38:40 +00:00
* @ param $lang
* Language to store the string in
2007-04-06 14:15:43 +00:00
* @ param $file
* Object representation of file being imported , only required when op is 'db-store'
2007-05-03 09:51:08 +00:00
* @ param $group
* Text group to import PO file into ( eg . 'default' for interface translations )
2006-02-05 15:42:56 +00:00
*/
2007-05-03 09:51:08 +00:00
function _locale_import_one_string ( $op , $value = NULL , $mode = NULL , $lang = NULL , $file = NULL , $group = 'default' ) {
2007-06-17 17:41:40 +00:00
static $report = array ( 0 , 0 , 0 );
2006-02-05 15:42:56 +00:00
static $headerdone = FALSE ;
2006-09-01 05:38:40 +00:00
static $strings = array ();
switch ( $op ) {
// Return stored strings
case 'mem-report' :
return $strings ;
// Store string in memory (only supports single strings)
case 'mem-store' :
$strings [ $value [ 'msgid' ]] = $value [ 'msgstr' ];
return ;
// Called at end of import to inform the user
case 'db-report' :
2007-06-17 17:41:40 +00:00
return array ( $headerdone , $report [ 0 ], $report [ 1 ], $report [ 2 ]);
2006-09-01 05:38:40 +00:00
2007-06-17 17:41:40 +00:00
// Store the string we got in the database.
2006-09-01 05:38:40 +00:00
case 'db-store' :
2007-06-17 17:41:40 +00:00
// We got header information.
2006-09-01 05:38:40 +00:00
if ( $value [ 'msgid' ] == '' ) {
2007-06-17 17:41:40 +00:00
$header = _locale_import_parse_header ( $value [ 'msgstr' ]);
2006-09-01 05:38:40 +00:00
2007-06-17 17:41:40 +00:00
// Get the plural formula and update in database.
if ( isset ( $header [ " Plural-Forms " ]) && $p = _locale_import_parse_plural_forms ( $header [ " Plural-Forms " ], $file -> filename )) {
2006-09-01 05:38:40 +00:00
list ( $nplurals , $plural ) = $p ;
2007-03-26 01:32:22 +00:00
db_query ( " UPDATE { languages} SET plurals = %d, formula = '%s' WHERE language = '%s' " , $nplurals , $plural , $lang );
2006-02-05 15:42:56 +00:00
}
2006-09-01 05:38:40 +00:00
else {
2007-03-26 01:32:22 +00:00
db_query ( " UPDATE { languages} SET plurals = %d, formula = '%s' WHERE language = '%s' " , 0 , '' , $lang );
2006-09-01 05:38:40 +00:00
}
$headerdone = TRUE ;
}
else {
2007-06-17 17:41:40 +00:00
// Some real string to import.
2007-05-08 09:48:14 +00:00
$comments = _locale_import_shorten_comments ( empty ( $value [ '#' ]) ? array () : $value [ '#' ]);
2007-06-22 08:32:28 +00:00
2006-09-01 05:38:40 +00:00
if ( strpos ( $value [ 'msgid' ], " \0 " )) {
2007-06-17 17:41:40 +00:00
// This string has plural versions.
2006-09-01 05:38:40 +00:00
$english = explode ( " \0 " , $value [ 'msgid' ], 2 );
$entries = array_keys ( $value [ 'msgstr' ]);
for ( $i = 3 ; $i <= count ( $entries ); $i ++ ) {
$english [] = $english [ 1 ];
}
$translation = array_map ( '_locale_import_append_plural' , $value [ 'msgstr' ], $entries );
$english = array_map ( '_locale_import_append_plural' , $english , $entries );
foreach ( $translation as $key => $trans ) {
if ( $key == 0 ) {
$plid = 0 ;
2006-02-05 15:42:56 +00:00
}
2007-06-17 17:41:40 +00:00
$plid = _locale_import_one_string_db ( $report , $lang , $english [ $key ], $trans , $group , $comments , $mode , $plid , $key );
2006-02-05 15:42:56 +00:00
}
}
2006-09-01 05:38:40 +00:00
else {
2007-06-17 17:41:40 +00:00
// A simple string to import.
2006-09-01 05:38:40 +00:00
$english = $value [ 'msgid' ];
$translation = $value [ 'msgstr' ];
2007-06-17 17:41:40 +00:00
_locale_import_one_string_db ( $report , $lang , $english , $translation , $group , $comments , $mode );
2006-02-05 15:42:56 +00:00
}
}
2006-09-01 05:38:40 +00:00
} // end of db-store operation
2004-08-11 11:26:20 +00:00
}
2007-06-17 17:41:40 +00:00
/**
* Import one string into the database .
*
* @ param $report
* Report array summarizing the number of changes done in the form :
* array ( inserts , updates , deletes ) .
* @ param $langcode
* Language code to import string into .
* @ param $source
* Source string .
* @ param $translation
* Translation to language specified in $langcode .
* @ param $textgroup
* Name of textgroup to store translation in .
* @ param $location
* Location value to save with source string .
* @ param $mode
* Import mode to use , LOCALE_IMPORT_KEEP or LOCALE_IMPORT_OVERWRITE .
* @ param $plid
* Optional plural ID to use .
* @ param $plural
* Optional plural value to use .
* @ return
* The string ID of the existing string modified or the new string added .
*/
function _locale_import_one_string_db ( & $report , $langcode , $source , $translation , $textgroup , $location , $mode , $plid = NULL , $plural = NULL ) {
$lid = db_result ( db_query ( " SELECT lid FROM { locales_source} WHERE source = '%s' AND textgroup = '%s' " , $source , $textgroup ));
if ( ! empty ( $translation )) {
if ( $lid ) {
// We have this source string saved already.
db_query ( " UPDATE { locales_source} SET location = '%s' WHERE lid = %d " , $location , $lid );
$exists = ( bool ) db_result ( db_query ( " SELECT lid FROM { locales_target} WHERE lid = %d AND language = '%s' " , $lid , $langcode ));
if ( ! $exists ) {
// No translation in this language.
db_query ( " INSERT INTO { locales_target} (lid, language, translation, plid, plural) VALUES (%d, '%s', '%s', %d, %d) " , $lid , $langcode , $translation , $plid , $plural );
$report [ 0 ] ++ ;
}
else if ( $mode == LOCALE_IMPORT_OVERWRITE ) {
2007-07-02 14:41:37 +00:00
// Translation exists, only overwrite if instructed.
2007-06-17 17:41:40 +00:00
db_query ( " UPDATE { locales_target} SET translation = '%s', plid = %d, plural = %d WHERE language = '%s' AND lid = %d " , $translation , $plid , $plural , $langcode , $lid );
$report [ 1 ] ++ ;
}
}
else {
// No such source string in the database yet.
db_query ( " INSERT INTO { locales_source} (location, source, textgroup) VALUES ('%s', '%s', '%s') " , $location , $source , $textgroup );
$lid = db_result ( db_query ( " SELECT lid FROM { locales_source} WHERE source = '%s' AND textgroup = '%s' " , $source , $textgroup ));
db_query ( " INSERT INTO { locales_target} (lid, language, translation, plid, plural) VALUES (%d, '%s', '%s', %d, %d) " , $lid , $langcode , $translation , $plid , $plural );
$report [ 0 ] ++ ;
}
}
elseif ( $mode == LOCALE_IMPORT_OVERWRITE ) {
// Empty translation, remove existing if instructed.
db_query ( " DELETE FROM { locales_target} WHERE language = '%s' AND lid = %d AND plid = %d AND plural = %d " , $translation , $langcode , $lid , $plid , $plural );
$report [ 2 ] ++ ;
}
2007-06-22 08:32:28 +00:00
2007-06-17 17:41:40 +00:00
return $lid ;
}
2004-08-11 11:26:20 +00:00
/**
* Parses a Gettext Portable Object file header
*
2007-05-08 09:46:24 +00:00
* @ param $header
* A string containing the complete header
* @ return
* An associative array of key - value pairs
2004-08-11 11:26:20 +00:00
*/
function _locale_import_parse_header ( $header ) {
2007-06-17 17:41:40 +00:00
$header_parsed = array ();
$lines = array_map ( 'trim' , explode ( " \n " , $header ));
2004-08-11 11:26:20 +00:00
foreach ( $lines as $line ) {
if ( $line ) {
list ( $tag , $contents ) = explode ( " : " , $line , 2 );
2007-06-17 17:41:40 +00:00
$header_parsed [ trim ( $tag )] = trim ( $contents );
2004-08-11 11:26:20 +00:00
}
}
2007-06-17 17:41:40 +00:00
return $header_parsed ;
2004-08-11 11:26:20 +00:00
}
/**
* Parses a Plural - Forms entry from a Gettext Portable Object file header
*
2006-09-01 05:38:40 +00:00
* @ param $pluralforms
* A string containing the Plural - Forms entry
* @ param $filename
* A string containing the filename
* @ return
* An array containing the number of plurals and a
* formula in PHP for computing the plural form
2004-08-11 11:26:20 +00:00
*/
2004-10-26 17:20:58 +00:00
function _locale_import_parse_plural_forms ( $pluralforms , $filename ) {
2004-08-11 11:26:20 +00:00
// First, delete all whitespace
$pluralforms = strtr ( $pluralforms , array ( " " => " " , " \t " => " " ));
// Select the parts that define nplurals and plural
$nplurals = strstr ( $pluralforms , " nplurals= " );
if ( strpos ( $nplurals , " ; " )) {
$nplurals = substr ( $nplurals , 9 , strpos ( $nplurals , " ; " ) - 9 );
}
else {
return FALSE ;
}
$plural = strstr ( $pluralforms , " plural= " );
if ( strpos ( $plural , " ; " )) {
$plural = substr ( $plural , 7 , strpos ( $plural , " ; " ) - 7 );
}
else {
return FALSE ;
}
// Get PHP version of the plural formula
$plural = _locale_import_parse_arithmetic ( $plural );
2006-07-06 14:41:37 +00:00
if ( $plural !== FALSE ) {
2004-08-11 11:26:20 +00:00
return array ( $nplurals , $plural );
}
else {
2006-09-09 08:25:24 +00:00
drupal_set_message ( t ( 'The translation file %filename contains an error: the plural formula could not be parsed.' , array ( '%filename' => $filename )), 'error' );
2004-08-11 11:26:20 +00:00
return FALSE ;
}
}
/**
* Parses and sanitizes an arithmetic formula into a PHP expression
*
* While parsing , we ensure , that the operators have the right
* precedence and associativity .
*
2007-05-08 09:46:24 +00:00
* @ param $string
* A string containing the arithmetic formula
* @ return
* The PHP version of the formula
2004-08-11 11:26:20 +00:00
*/
function _locale_import_parse_arithmetic ( $string ) {
// Operator precedence table
$prec = array ( " ( " => - 1 , " ) " => - 1 , " ? " => 1 , " : " => 1 , " || " => 3 , " && " => 4 , " == " => 5 , " != " => 5 , " < " => 6 , " > " => 6 , " <= " => 6 , " >= " => 6 , " + " => 7 , " - " => 7 , " * " => 8 , " / " => 8 , " % " => 8 );
// Right associativity
$rasc = array ( " ? " => 1 , " : " => 1 );
$tokens = _locale_import_tokenize_formula ( $string );
// Parse by converting into infix notation then back into postfix
$opstk = array ();
$elstk = array ();
foreach ( $tokens as $token ) {
$ctok = $token ;
// Numbers and the $n variable are simply pushed into $elarr
if ( is_numeric ( $token )) {
$elstk [] = $ctok ;
}
elseif ( $ctok == " n " ) {
$elstk [] = '$n' ;
}
elseif ( $ctok == " ( " ) {
$opstk [] = $ctok ;
}
elseif ( $ctok == " ) " ) {
$topop = array_pop ( $opstk );
2007-05-03 09:51:08 +00:00
while ( isset ( $topop ) && ( $topop != " ( " )) {
2004-08-11 11:26:20 +00:00
$elstk [] = $topop ;
$topop = array_pop ( $opstk );
}
}
2007-04-04 20:47:41 +00:00
elseif ( ! empty ( $prec [ $ctok ])) {
2004-08-11 11:26:20 +00:00
// If it's an operator, then pop from $oparr into $elarr until the
// precedence in $oparr is less than current, then push into $oparr
$topop = array_pop ( $opstk );
2007-05-03 09:51:08 +00:00
while ( isset ( $topop ) && ( $prec [ $topop ] >= $prec [ $ctok ]) && ! (( $prec [ $topop ] == $prec [ $ctok ]) && ! empty ( $rasc [ $topop ]) && ! empty ( $rasc [ $ctok ]))) {
2004-08-11 11:26:20 +00:00
$elstk [] = $topop ;
$topop = array_pop ( $opstk );
}
if ( $topop ) {
$opstk [] = $topop ; // Return element to top
}
$opstk [] = $ctok ; // Parentheses are not needed
}
else {
2006-07-05 11:45:51 +00:00
return FALSE ;
2004-08-11 11:26:20 +00:00
}
}
// Flush operator stack
$topop = array_pop ( $opstk );
while ( $topop != NULL ) {
$elstk [] = $topop ;
$topop = array_pop ( $opstk );
}
// Now extract formula from stack
$prevsize = count ( $elstk ) + 1 ;
while ( count ( $elstk ) < $prevsize ) {
$prevsize = count ( $elstk );
for ( $i = 2 ; $i < count ( $elstk ); $i ++ ) {
$op = $elstk [ $i ];
2007-05-03 09:51:08 +00:00
if ( ! empty ( $prec [ $op ])) {
2004-08-11 11:26:20 +00:00
$f = " " ;
if ( $op == " : " ) {
2008-04-14 17:48:46 +00:00
$f = $elstk [ $i - 2 ] . " ): " . $elstk [ $i - 1 ] . " ) " ;
2004-08-11 11:26:20 +00:00
}
elseif ( $op == " ? " ) {
2008-04-14 17:48:46 +00:00
$f = " ( " . $elstk [ $i - 2 ] . " ?( " . $elstk [ $i - 1 ];
2004-08-11 11:26:20 +00:00
}
else {
2008-04-14 17:48:46 +00:00
$f = " ( " . $elstk [ $i - 2 ] . $op . $elstk [ $i - 1 ] . " ) " ;
2004-08-11 11:26:20 +00:00
}
array_splice ( $elstk , $i - 2 , 3 , $f );
break ;
}
}
}
// If only one element is left, the number of operators is appropriate
if ( count ( $elstk ) == 1 ) {
return $elstk [ 0 ];
}
else {
return FALSE ;
}
}
/**
* Backward compatible implementation of token_get_all () for formula parsing
*
2007-05-08 09:46:24 +00:00
* @ param $string
* A string containing the arithmetic formula
* @ return
* The PHP version of the formula
2004-08-11 11:26:20 +00:00
*/
function _locale_import_tokenize_formula ( $formula ) {
$formula = str_replace ( " " , " " , $formula );
$tokens = array ();
for ( $i = 0 ; $i < strlen ( $formula ); $i ++ ) {
2006-01-15 07:14:14 +00:00
if ( is_numeric ( $formula [ $i ])) {
$num = $formula [ $i ];
2004-08-11 11:26:20 +00:00
$j = $i + 1 ;
2007-01-02 05:05:38 +00:00
while ( $j < strlen ( $formula ) && is_numeric ( $formula [ $j ])) {
2006-01-15 07:14:14 +00:00
$num .= $formula [ $j ];
2004-08-11 11:26:20 +00:00
$j ++ ;
}
$i = $j - 1 ;
$tokens [] = $num ;
}
2006-01-15 07:14:14 +00:00
elseif ( $pos = strpos ( " =<>!&| " , $formula [ $i ])) { // We won't have a space
$next = $formula [ $i + 1 ];
2004-08-11 11:26:20 +00:00
switch ( $pos ) {
case 1 :
case 2 :
case 3 :
case 4 :
if ( $next == '=' ) {
2008-04-14 17:48:46 +00:00
$tokens [] = $formula [ $i ] . '=' ;
2004-08-11 11:26:20 +00:00
$i ++ ;
}
else {
2006-01-15 07:14:14 +00:00
$tokens [] = $formula [ $i ];
2004-08-11 11:26:20 +00:00
}
break ;
case 5 :
if ( $next == '&' ) {
$tokens [] = '&&' ;
$i ++ ;
}
else {
2006-01-15 07:14:14 +00:00
$tokens [] = $formula [ $i ];
2004-08-11 11:26:20 +00:00
}
break ;
case 6 :
if ( $next == '|' ) {
$tokens [] = '||' ;
$i ++ ;
}
else {
2006-01-15 07:14:14 +00:00
$tokens [] = $formula [ $i ];
2004-08-11 11:26:20 +00:00
}
break ;
}
}
else {
2006-01-15 07:14:14 +00:00
$tokens [] = $formula [ $i ];
2004-08-11 11:26:20 +00:00
}
}
return $tokens ;
}
/**
* Modify a string to contain proper count indices
*
* This is a callback function used via array_map ()
*
2007-05-08 09:46:24 +00:00
* @ param $entry
* An array element
* @ param $key
* Index of the array element
2004-08-11 11:26:20 +00:00
*/
function _locale_import_append_plural ( $entry , $key ) {
2004-08-12 18:00:11 +00:00
// No modifications for 0, 1
2004-08-11 11:26:20 +00:00
if ( $key == 0 || $key == 1 ) {
return $entry ;
}
// First remove any possibly false indices, then add new ones
2006-08-18 12:17:00 +00:00
$entry = preg_replace ( '/(@count)\[[0-9]\]/' , '\\1' , $entry );
return preg_replace ( '/(@count)/' , " \\ 1[ $key ] " , $entry );
2004-08-11 11:26:20 +00:00
}
/**
* Generate a short , one string version of the passed comment array
*
2007-05-08 09:46:24 +00:00
* @ param $comment
* An array of strings containing a comment
* @ return
* Short one string version of the comment
2004-08-11 11:26:20 +00:00
*/
function _locale_import_shorten_comments ( $comment ) {
$comm = '' ;
2005-07-29 18:56:58 +00:00
while ( count ( $comment )) {
2008-04-14 17:48:46 +00:00
$test = $comm . substr ( array_shift ( $comment ), 1 ) . ', ' ;
2005-07-29 18:56:58 +00:00
if ( strlen ( $comm ) < 130 ) {
$comm = $test ;
}
else {
break ;
}
2004-08-11 11:26:20 +00:00
}
return substr ( $comm , 0 , - 2 );
}
/**
* Parses a string in quotes
*
2007-05-08 09:46:24 +00:00
* @ param $string
* A string specified with enclosing quotes
* @ return
* The string parsed from inside the quotes
2004-08-11 11:26:20 +00:00
*/
function _locale_import_parse_quoted ( $string ) {
if ( substr ( $string , 0 , 1 ) != substr ( $string , - 1 , 1 )) {
return FALSE ; // Start and end quotes must be the same
}
$quote = substr ( $string , 0 , 1 );
$string = substr ( $string , 1 , - 1 );
if ( $quote == '"' ) { // Double quotes: strip slashes
return stripcslashes ( $string );
}
elseif ( $quote == " ' " ) { // Simple quote: return as-is
return $string ;
}
else {
return FALSE ; // Unrecognized quote
}
}
2007-05-03 09:51:08 +00:00
/**
* @ } End of " locale-api-import "
*/
2007-06-08 12:51:59 +00:00
/**
* Parses a JavaScript file , extracts strings wrapped in Drupal . t () and
* Drupal . formatPlural () and inserts them into the database .
*/
function _locale_parse_js_file ( $filepath ) {
global $language ;
// Load the JavaScript file.
$file = file_get_contents ( $filepath );
// Match all calls to Drupal.t() in an array.
// Note: \s also matches newlines with the 's' modifier.
2008-04-14 17:48:46 +00:00
preg_match_all ( '~[^\w]Drupal\s*\.\s*t\s*\(\s*(' . LOCALE_JS_STRING . ')\s*[,\)]~s' , $file , $t_matches );
2007-06-08 12:51:59 +00:00
// Match all Drupal.formatPlural() calls in another array.
2008-04-14 17:48:46 +00:00
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 );
2007-06-08 12:51:59 +00:00
// Loop through all matches and process them.
$all_matches = array_merge ( $plural_matches [ 1 ], $t_matches [ 1 ]);
foreach ( $all_matches as $key => $string ) {
$strings = array ( $string );
// If there is also a plural version of this string, add it to the strings array.
if ( isset ( $plural_matches [ 2 ][ $key ])) {
$strings [] = $plural_matches [ 2 ][ $key ];
}
foreach ( $strings as $key => $string ) {
// Remove the quotes and string concatenations from the string.
$string = implode ( '' , preg_split ( '~(?<!\\\\)[\'"]\s*\+\s*[\'"]~s' , substr ( $string , 1 , - 1 )));
$result = db_query ( " SELECT lid, location FROM { locales_source} WHERE source = '%s' AND textgroup = 'default' " , $string );
if ( $source = db_fetch_object ( $result )) {
// We already have this source string and now have to add the location
// to the location column, if this file is not yet present in there.
$locations = preg_split ( '~\s*;\s*~' , $source -> location );
if ( ! in_array ( $filepath , $locations )) {
$locations [] = $filepath ;
$locations = implode ( '; ' , $locations );
// Save the new locations string to the database.
db_query ( " UPDATE { locales_source} SET location = '%s' WHERE lid = %d " , $locations , $source -> lid );
}
}
else {
// We don't have the source string yet, thus we insert it into the database.
db_query ( " INSERT INTO { locales_source} (location, source, textgroup) VALUES ('%s', '%s', 'default') " , $filepath , $string );
}
}
}
}
2007-05-03 09:51:08 +00:00
/**
* @ defgroup locale - api - export Translation ( template ) export API .
* @ {
*/
2004-08-11 11:26:20 +00:00
/**
2007-06-23 20:45:36 +00:00
* Generates a structured array of all strings with translations in
* $language , if given . This array can be used to generate an export
* of the string in the database .
2004-08-11 11:26:20 +00:00
*
2007-03-28 14:08:23 +00:00
* @ param $language
2007-06-23 20:45:36 +00:00
* Language object to generate the output for , or NULL if generating
2007-03-28 14:08:23 +00:00
* translation template .
2007-05-03 09:51:08 +00:00
* @ param $group
* Text group to export PO file from ( eg . 'default' for interface translations )
2004-08-11 11:26:20 +00:00
*/
2007-06-23 20:45:36 +00:00
function _locale_export_get_strings ( $language = NULL , $group = 'default' ) {
2007-03-28 14:08:23 +00:00
if ( isset ( $language )) {
2007-09-01 12:50:47 +00:00
$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 );
2004-08-11 11:26:20 +00:00
}
else {
2007-06-17 17:41:40 +00:00
$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 );
2004-08-11 11:26:20 +00:00
}
2007-06-23 20:45:36 +00:00
$strings = array ();
2004-08-11 11:26:20 +00:00
while ( $child = db_fetch_object ( $result )) {
2007-06-23 20:45:36 +00:00
$string = array (
'comment' => $child -> location ,
'source' => $child -> source ,
'translation' => isset ( $child -> translation ) ? $child -> translation : ''
);
if ( $child -> plid ) {
// Has a parent lid. Since we process in the order of plids,
// we already have the parent in the array, so we can add the
// lid to the next plural version to it. This builds a linked
// list of plurals.
$string [ 'child' ] = TRUE ;
$strings [ $child -> plid ][ 'plural' ] = $child -> lid ;
2004-08-11 11:26:20 +00:00
}
2007-06-23 20:45:36 +00:00
$strings [ $child -> lid ] = $string ;
2004-08-11 11:26:20 +00:00
}
2007-06-23 20:45:36 +00:00
return $strings ;
}
2004-08-12 18:00:11 +00:00
2007-06-23 20:45:36 +00:00
/**
* Generates the PO ( T ) file contents for given strings .
2007-06-28 07:48:41 +00:00
*
2007-06-23 20:45:36 +00:00
* @ param $language
* Language object to generate the output for , or NULL if generating
* translation template .
* @ param $strings
* Array of strings to export . See _locale_export_get_strings ()
* on how it should be formatted .
* @ param $header
* The header portion to use for the output file . Defaults
* are provided for PO and POT files .
*/
function _locale_export_po_generate ( $language = NULL , $strings = array (), $header = NULL ) {
global $user ;
2007-06-28 07:48:41 +00:00
2007-06-23 20:45:36 +00:00
if ( ! isset ( $header )) {
if ( isset ( $language )) {
2008-04-14 17:48:46 +00:00
$header = '# ' . $language -> name . ' translation of ' . variable_get ( 'site_name' , 'Drupal' ) . " \n " ;
$header .= '# Generated by ' . $user -> name . ' <' . $user -> mail . " > \n " ;
2007-06-23 20:45:36 +00:00
$header .= " # \n " ;
$header .= " msgid \" \" \n " ;
$header .= " msgstr \" \" \n " ;
$header .= " \" Project-Id-Version: PROJECT VERSION \\ n \" \n " ;
2008-04-14 17:48:46 +00:00
$header .= " \" POT-Creation-Date: " . date ( " Y-m-d H:iO " ) . " \\ n \" \n " ;
$header .= " \" PO-Revision-Date: " . date ( " Y-m-d H:iO " ) . " \\ n \" \n " ;
2007-06-23 20:45:36 +00:00
$header .= " \" Last-Translator: NAME <EMAIL@ADDRESS> \\ n \" \n " ;
$header .= " \" Language-Team: LANGUAGE <EMAIL@ADDRESS> \\ n \" \n " ;
$header .= " \" MIME-Version: 1.0 \\ n \" \n " ;
$header .= " \" Content-Type: text/plain; charset=utf-8 \\ n \" \n " ;
$header .= " \" Content-Transfer-Encoding: 8bit \\ n \" \n " ;
if ( $language -> formula && $language -> plurals ) {
2008-04-14 17:48:46 +00:00
$header .= " \" Plural-Forms: nplurals= " . $language -> plurals . " ; plural= " . strtr ( $language -> formula , array ( '$' => '' )) . " ; \\ n \" \n " ;
2007-06-23 20:45:36 +00:00
}
}
else {
$header = " # LANGUAGE translation of PROJECT \n " ;
$header .= " # Copyright (c) YEAR NAME <EMAIL@ADDRESS> \n " ;
$header .= " # \n " ;
$header .= " msgid \" \" \n " ;
$header .= " msgstr \" \" \n " ;
$header .= " \" Project-Id-Version: PROJECT VERSION \\ n \" \n " ;
2008-04-14 17:48:46 +00:00
$header .= " \" POT-Creation-Date: " . date ( " Y-m-d H:iO " ) . " \\ n \" \n " ;
2007-06-23 20:45:36 +00:00
$header .= " \" PO-Revision-Date: YYYY-mm-DD HH:MM+ZZZZ \\ n \" \n " ;
$header .= " \" Last-Translator: NAME <EMAIL@ADDRESS> \\ n \" \n " ;
$header .= " \" Language-Team: LANGUAGE <EMAIL@ADDRESS> \\ n \" \n " ;
$header .= " \" MIME-Version: 1.0 \\ n \" \n " ;
$header .= " \" Content-Type: text/plain; charset=utf-8 \\ n \" \n " ;
$header .= " \" Content-Transfer-Encoding: 8bit \\ n \" \n " ;
$header .= " \" Plural-Forms: nplurals=INTEGER; plural=EXPRESSION; \\ n \" \n " ;
2004-08-11 11:26:20 +00:00
}
}
2007-06-28 07:48:41 +00:00
2008-04-14 17:48:46 +00:00
$output = $header . " \n " ;
2007-06-28 07:48:41 +00:00
2007-06-23 20:45:36 +00:00
foreach ( $strings as $lid => $string ) {
// Only process non-children, children are output below their parent.
if ( ! isset ( $string [ 'child' ])) {
if ( $string [ 'comment' ]) {
2008-04-14 17:48:46 +00:00
$output .= '#: ' . $string [ 'comment' ] . " \n " ;
2004-08-11 11:26:20 +00:00
}
2008-04-14 17:48:46 +00:00
$output .= 'msgid ' . _locale_export_string ( $string [ 'source' ]);
2007-06-23 20:45:36 +00:00
if ( ! empty ( $string [ 'plural' ])) {
$plural = $string [ 'plural' ];
2008-04-14 17:48:46 +00:00
$output .= 'msgid_plural ' . _locale_export_string ( $strings [ $plural ][ 'source' ]);
2007-03-28 14:08:23 +00:00
if ( isset ( $language )) {
2007-06-23 20:45:36 +00:00
$translation = $string [ 'translation' ];
for ( $i = 0 ; $i < $language -> plurals ; $i ++ ) {
2008-04-14 17:48:46 +00:00
$output .= 'msgstr[' . $i . '] ' . _locale_export_string ( $translation );
2006-09-05 11:40:44 +00:00
if ( $plural ) {
2007-06-23 20:45:36 +00:00
$translation = _locale_export_remove_plural ( $strings [ $plural ][ 'translation' ]);
$plural = isset ( $strings [ $plural ][ 'plural' ]) ? $strings [ $plural ][ 'plural' ] : 0 ;
2006-09-05 11:40:44 +00:00
}
else {
$translation = '' ;
}
2004-08-11 11:26:20 +00:00
}
}
else {
2008-04-14 17:48:46 +00:00
$output .= 'msgstr[0] ""' . " \n " ;
$output .= 'msgstr[1] ""' . " \n " ;
2004-08-11 11:26:20 +00:00
}
}
else {
2008-04-14 17:48:46 +00:00
$output .= 'msgstr ' . _locale_export_string ( $string [ 'translation' ]);
2004-08-11 11:26:20 +00:00
}
2007-06-23 20:45:36 +00:00
$output .= " \n " ;
2004-08-11 11:26:20 +00:00
}
}
2007-06-23 20:45:36 +00:00
return $output ;
}
/**
* Write a generated PO or POT file to the output .
*
* @ param $language
* Language object to generate the output for , or NULL if generating
* translation template .
* @ param $output
* The PO ( T ) file to output as a string . See _locale_export_generate_po ()
* on how it can be generated .
*/
function _locale_export_po ( $language = NULL , $output = NULL ) {
// Log the export event.
if ( isset ( $language )) {
2008-04-14 17:48:46 +00:00
$filename = $language -> language . '.po' ;
2007-06-23 20:45:36 +00:00
watchdog ( 'locale' , 'Exported %locale translation file: %filename.' , array ( '%locale' => $language -> name , '%filename' => $filename ));
}
else {
$filename = 'drupal.pot' ;
watchdog ( 'locale' , 'Exported translation file: %filename.' , array ( '%filename' => $filename ));
}
// Download the file fo the client.
header ( " Content-Disposition: attachment; filename= $filename " );
header ( " Content-Type: text/plain; charset=utf-8 " );
print $output ;
2004-08-11 11:26:20 +00:00
die ();
}
/**
* Print out a string on multiple lines
*/
2007-06-23 20:45:36 +00:00
function _locale_export_string ( $str ) {
2004-08-11 11:26:20 +00:00
$stri = addcslashes ( $str , " \0 .. \37 \\ \" " );
$parts = array ();
// Cut text into several lines
while ( $stri != " " ) {
$i = strpos ( $stri , " \\ n " );
if ( $i === FALSE ) {
$curstr = $stri ;
$stri = " " ;
}
else {
$curstr = substr ( $stri , 0 , $i + 2 );
$stri = substr ( $stri , $i + 2 );
}
$curparts = explode ( " \n " , _locale_export_wrap ( $curstr , 70 ));
$parts = array_merge ( $parts , $curparts );
}
2007-03-28 14:08:23 +00:00
// Multiline string
2004-08-11 11:26:20 +00:00
if ( count ( $parts ) > 1 ) {
2008-04-14 17:48:46 +00:00
return " \" \" \n \" " . implode ( " \" \n \" " , $parts ) . " \" \n " ;
2004-08-11 11:26:20 +00:00
}
2007-03-28 14:08:23 +00:00
// Single line string
elseif ( count ( $parts ) == 1 ) {
2004-08-11 11:26:20 +00:00
return " \" $parts[0] \" \n " ;
}
2007-03-28 14:08:23 +00:00
// No translation
else {
return " \" \" \n " ;
}
2004-08-11 11:26:20 +00:00
}
/**
* Custom word wrapping for Portable Object ( Template ) files .
*/
function _locale_export_wrap ( $str , $len ) {
2006-01-13 14:38:38 +00:00
$words = explode ( ' ' , $str );
2004-08-11 11:26:20 +00:00
$ret = array ();
$cur = " " ;
$nstr = 1 ;
while ( count ( $words )) {
$word = array_shift ( $words );
if ( $nstr ) {
$cur = $word ;
$nstr = 0 ;
}
elseif ( strlen ( " $cur $word " ) > $len ) {
2008-04-14 17:48:46 +00:00
$ret [] = $cur . " " ;
2004-08-11 11:26:20 +00:00
$cur = $word ;
}
else {
$cur = " $cur $word " ;
}
}
$ret [] = $cur ;
return implode ( " \n " , $ret );
}
/**
* Removes plural index information from a string
*/
function _locale_export_remove_plural ( $entry ) {
2006-08-18 12:17:00 +00:00
return preg_replace ( '/(@count)\[[0-9]\]/' , '\\1' , $entry );
2004-08-11 11:26:20 +00:00
}
/**
2007-05-03 09:51:08 +00:00
* @ } End of " locale-api-export "
2004-08-11 11:26:20 +00:00
*/
/**
2007-05-03 09:51:08 +00:00
* @ defgroup locale - api - seek String search functions .
* @ {
2004-08-11 11:26:20 +00:00
*/
/**
* Perform a string search and display results in a table
*/
2007-05-03 09:51:08 +00:00
function _locale_translate_seek () {
2007-03-26 01:32:22 +00:00
$output = '' ;
2005-03-31 21:18:08 +00:00
// We have at least one criterion to match
2007-05-03 09:51:08 +00:00
if ( $query = _locale_translate_seek_query ()) {
2007-06-17 17:41:40 +00:00
$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 " ;
2004-08-11 11:26:20 +00:00
2006-01-05 23:35:34 +00:00
$arguments = array ();
2007-09-01 12:50:47 +00:00
$limit_language = FALSE ;
2004-08-11 11:26:20 +00:00
// Compute LIKE section
2007-05-03 09:51:08 +00:00
switch ( $query [ 'translation' ]) {
2004-08-11 11:26:20 +00:00
case 'translated' :
2008-08-21 19:36:39 +00:00
$where = " WHERE (t.translation LIKE ?) " ;
2004-08-11 11:26:20 +00:00
$orderby = " ORDER BY t.translation " ;
2008-08-21 19:36:39 +00:00
$arguments [] = '%' . $query [ 'string' ] . '%' ;
2004-08-11 11:26:20 +00:00
break ;
case 'untranslated' :
2008-08-21 19:36:39 +00:00
$where = " WHERE (s.source LIKE ? AND t.translation IS NULL) " ;
2004-08-11 11:26:20 +00:00
$orderby = " ORDER BY s.source " ;
2008-08-21 19:36:39 +00:00
$arguments [] = '%' . $query [ 'string' ] . '%' ;
2004-08-11 11:26:20 +00:00
break ;
case 'all' :
default :
2008-08-21 19:36:39 +00:00
$where = " WHERE (s.source LIKE ? OR t.translation LIKE ?) " ;
2004-08-11 11:26:20 +00:00
$orderby = '' ;
2008-08-21 19:36:39 +00:00
$arguments [] = '%' . $query [ 'string' ] . '%' ;
$arguments [] = '%' . $query [ 'string' ] . '%' ;
2004-08-11 11:26:20 +00:00
break ;
}
2007-05-03 09:51:08 +00:00
$grouplimit = '' ;
if ( ! empty ( $query [ 'group' ]) && $query [ 'group' ] != 'all' ) {
2008-08-21 19:36:39 +00:00
$grouplimit = " AND s.textgroup = ? " ;
2007-05-03 09:51:08 +00:00
$arguments [] = $query [ 'group' ];
}
2004-08-11 11:26:20 +00:00
2007-03-26 01:32:22 +00:00
switch ( $query [ 'language' ]) {
2004-08-11 11:26:20 +00:00
// Force search in source strings
case " en " :
2008-08-21 19:36:39 +00:00
$sql = $join . " WHERE s.source LIKE ? $grouplimit ORDER BY s.source " ;
$arguments = array ( '%' . $query [ 'string' ] . '%' ); // $where is not used, discard its arguments
2007-05-03 09:51:08 +00:00
if ( ! empty ( $grouplimit )) {
$arguments [] = $query [ 'group' ];
}
2004-08-11 11:26:20 +00:00
break ;
// Search in all languages
case " all " :
2007-05-03 09:51:08 +00:00
$sql = " $join $where $grouplimit $orderby " ;
2004-08-11 11:26:20 +00:00
break ;
// Some different language
default :
2008-08-21 19:36:39 +00:00
$sql = " $join AND t.language = ? $where $grouplimit $orderby " ;
2007-09-01 12:50:47 +00:00
array_unshift ( $arguments , $query [ 'language' ]);
// Don't show translation flags for other languages, we can't see them with this search.
$limit_language = $query [ 'language' ];
2004-08-11 11:26:20 +00:00
}
2006-01-05 23:35:34 +00:00
$result = pager_query ( $sql , 50 , 0 , NULL , $arguments );
2004-08-11 11:26:20 +00:00
2007-05-03 09:51:08 +00:00
$groups = module_invoke_all ( 'locale' , 'groups' );
2007-09-01 12:50:47 +00:00
$header = array ( t ( 'Text group' ), t ( 'String' ), ( $limit_language ) ? t ( 'Language' ) : t ( 'Languages' ), array ( 'data' => t ( 'Operations' ), 'colspan' => '2' ));
2004-08-11 11:26:20 +00:00
$arr = array ();
while ( $locale = db_fetch_object ( $result )) {
2007-05-03 09:51:08 +00:00
$arr [ $locale -> lid ][ 'group' ] = $groups [ $locale -> textgroup ];
$arr [ $locale -> lid ][ 'languages' ][ $locale -> language ] = $locale -> translation ;
2004-08-11 11:26:20 +00:00
$arr [ $locale -> lid ][ 'location' ] = $locale -> location ;
$arr [ $locale -> lid ][ 'source' ] = $locale -> source ;
}
2007-03-26 01:32:22 +00:00
$rows = array ();
2004-08-11 11:26:20 +00:00
foreach ( $arr as $lid => $value ) {
2007-09-01 12:50:47 +00:00
$rows [] = array (
$value [ 'group' ],
2008-04-14 17:48:46 +00:00
array ( 'data' => check_plain ( truncate_utf8 ( $value [ 'source' ], 150 , FALSE , TRUE )) . '<br /><small>' . $value [ 'location' ] . '</small>' ),
2007-09-01 12:50:47 +00:00
array ( 'data' => _locale_translate_language_list ( $value [ 'languages' ], $limit_language ), 'align' => 'center' ),
array ( 'data' => l ( t ( 'edit' ), " admin/build/translate/edit/ $lid " ), 'class' => 'nowrap' ),
array ( 'data' => l ( t ( 'delete' ), " admin/build/translate/delete/ $lid " ), 'class' => 'nowrap' ),
);
2004-08-11 11:26:20 +00:00
}
2005-10-07 06:11:12 +00:00
if ( count ( $rows )) {
$output .= theme ( 'table' , $header , $rows );
2007-03-28 14:08:23 +00:00
if ( $pager = theme ( 'pager' , NULL , 50 )) {
$output .= $pager ;
}
2005-10-07 06:11:12 +00:00
}
2007-03-28 14:08:23 +00:00
else {
$output .= t ( 'No strings found for your search.' );
2005-10-07 06:11:12 +00:00
}
2004-08-11 11:26:20 +00:00
}
return $output ;
}
2007-05-03 09:51:08 +00:00
/**
* Build array out of search criteria specified in request variables
*/
function _locale_translate_seek_query () {
static $query = NULL ;
if ( ! isset ( $query )) {
$query = array ();
$fields = array ( 'string' , 'language' , 'translation' , 'group' );
foreach ( $fields as $field ) {
if ( isset ( $_REQUEST [ $field ])) {
$query [ $field ] = $_REQUEST [ $field ];
}
}
}
return $query ;
}
2007-11-26 22:34:09 +00:00
/**
* Force the JavaScript translation file ( s ) to be refreshed .
*
* This function sets a refresh flag for a specified language , or all
* languages except English , if none specified . JavaScript translation
* files are rebuilt ( with locale_update_js_files ()) the next time a
* request is served in that language .
*
* @ param $langcode
* The language code for which the file needs to be refreshed .
* @ return
* New content of the 'javascript_parsed' variable .
*/
function _locale_invalidate_js ( $langcode = NULL ) {
$parsed = variable_get ( 'javascript_parsed' , array ());
if ( empty ( $langcode )) {
// Invalidate all languages.
$languages = language_list ();
unset ( $languages [ 'en' ]);
foreach ( $languages as $lcode => $data ) {
2008-04-14 17:48:46 +00:00
$parsed [ 'refresh:' . $lcode ] = 'waiting' ;
2007-11-26 22:34:09 +00:00
}
}
else {
// Invalidate single language.
2008-04-14 17:48:46 +00:00
$parsed [ 'refresh:' . $langcode ] = 'waiting' ;
2007-11-26 22:34:09 +00:00
}
variable_set ( 'javascript_parsed' , $parsed );
return $parsed ;
}
2007-06-08 12:51:59 +00:00
/**
* ( Re - ) Creates the JavaScript translation file for a language .
*
* @ param $language
* The language , the translation file should be ( re ) created for .
*/
function _locale_rebuild_js ( $langcode = NULL ) {
if ( ! isset ( $langcode )) {
global $language ;
}
else {
// Get information about the locale.
$languages = language_list ();
$language = $languages [ $langcode ];
}
// Construct the array for JavaScript translations.
// We sort on plural so that we have all plural forms before singular forms.
2008-08-21 19:36:39 +00:00
$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 = : language
WHERE s . location LIKE '%.js%'
AND s . textgroup = 'default'
ORDER BY t . plural DESC " , array(':language' => $language->language ));
2007-06-08 12:51:59 +00:00
$translations = $plurals = array ();
while ( $data = db_fetch_object ( $result )) {
// Only add this to the translations array when there is actually a translation.
if ( ! empty ( $data -> translation )) {
if ( $data -> plural ) {
// When the translation is a plural form, first add it to another array and
// wait for the singular (parent) translation.
if ( ! isset ( $plurals [ $data -> plid ])) {
$plurals [ $data -> plid ] = array ( $data -> plural => $data -> translation );
}
else {
$plurals [ $data -> plid ] += array ( $data -> plural => $data -> translation );
}
}
elseif ( isset ( $plurals [ $data -> lid ])) {
// There are plural translations for this translation, so get them from
// the plurals array and add them to the final translations array.
$translations [ $data -> source ] = array ( $data -> plural => $data -> translation ) + $plurals [ $data -> lid ];
unset ( $plurals [ $data -> lid ]);
}
else {
// There are no plural forms for this translation, so just add it to
// the translations array.
$translations [ $data -> source ] = $data -> translation ;
}
}
}
2007-11-26 22:34:09 +00:00
// Construct the JavaScript file, if there are translations.
$data = $status = '' ;
2007-06-08 12:51:59 +00:00
if ( ! empty ( $translations )) {
2007-11-26 22:34:09 +00:00
2007-06-08 12:51:59 +00:00
$data = " Drupal.locale = { " ;
if ( ! empty ( $language -> formula )) {
$data .= " 'pluralFormula': function( \$ n) { return Number( { $language -> formula } ); }, " ;
}
2008-04-14 17:48:46 +00:00
$data .= " 'strings': " . drupal_to_js ( $translations ) . " }; " ;
2007-06-08 12:51:59 +00:00
$data_hash = md5 ( $data );
2007-11-26 22:34:09 +00:00
}
2007-06-08 12:51:59 +00:00
2007-11-26 22:34:09 +00:00
// Construct the filepath where JS translation files are stored.
// There is (on purpose) no front end to edit that variable.
$dir = file_create_path ( variable_get ( 'locale_js_directory' , 'languages' ));
2007-06-08 12:51:59 +00:00
2007-11-26 22:34:09 +00:00
// Delete old file, if we have no translations anymore, or a different file to be saved.
if ( ! empty ( $language -> javascript ) && ( ! $data || $language -> javascript != $data_hash )) {
2008-04-14 17:48:46 +00:00
file_delete ( file_create_path ( $dir . '/' . $language -> language . '_' . $language -> javascript . '.js' ));
2007-11-26 22:34:09 +00:00
$language -> javascript = '' ;
$status = 'deleted' ;
}
2007-06-08 12:51:59 +00:00
2007-11-26 22:34:09 +00:00
// Only create a new file if the content has changed.
if ( $data && $language -> javascript != $data_hash ) {
// Ensure that the directory exists and is writable, if possible.
file_check_directory ( $dir , TRUE );
2007-06-08 12:51:59 +00:00
2007-11-26 22:34:09 +00:00
// Save the file.
2008-04-14 17:48:46 +00:00
$dest = $dir . '/' . $language -> language . '_' . $data_hash . '.js' ;
2007-11-26 22:34:09 +00:00
if ( file_save_data ( $data , $dest )) {
$language -> javascript = $data_hash ;
$status = ( $status == 'deleted' ) ? 'updated' : 'created' ;
}
else {
$language -> javascript = '' ;
$status = 'error' ;
}
}
2007-06-08 12:51:59 +00:00
2007-11-26 22:34:09 +00:00
// Save the new JavaScript hash (or an empty value if the file
// just got deleted). Act only if some operation was executed.
if ( $status ) {
db_query ( " UPDATE { languages} SET javascript = '%s' WHERE language = '%s' " , $language -> javascript , $language -> language );
// Update the default language variable if the default language has been altered.
// This is necessary to keep the variable consistent with the database
// version of the language and to prevent checking against an outdated hash.
$default_langcode = language_default ( 'language' );
if ( $default_langcode == $language -> language ) {
$default = db_fetch_object ( db_query ( " SELECT * FROM { languages} WHERE language = '%s' " , $default_langcode ));
variable_set ( 'language_default' , $default );
2007-06-08 12:51:59 +00:00
}
}
2007-11-26 22:34:09 +00:00
// Log the operation and return success flag.
switch ( $status ) {
case 'updated' :
watchdog ( 'locale' , 'Updated JavaScript translation file for the language %language.' , array ( '%language' => t ( $language -> name )));
return TRUE ;
case 'created' :
watchdog ( 'locale' , 'Created JavaScript translation file for the language %language.' , array ( '%language' => t ( $language -> name )));
return TRUE ;
case 'deleted' :
watchdog ( 'locale' , 'Removed JavaScript translation file for the language %language, because no translations currently exist for that language.' , array ( '%language' => t ( $language -> name )));
return TRUE ;
case 'error' :
watchdog ( 'locale' , 'An error occurred during creation of the JavaScript translation file for the language %language.' , array ( '%language' => t ( $language -> name )), WATCHDOG_ERROR );
return FALSE ;
default :
// No operation needed.
return TRUE ;
2007-06-08 12:51:59 +00:00
}
}
2007-05-03 09:51:08 +00:00
/**
* List languages in search result table
*/
2007-09-01 12:50:47 +00:00
function _locale_translate_language_list ( $translation , $limit_language ) {
2007-05-03 09:51:08 +00:00
// Add CSS
2008-04-14 17:48:46 +00:00
drupal_add_css ( drupal_get_path ( 'module' , 'locale' ) . '/locale.css' , 'module' , 'all' , FALSE );
2007-05-03 09:51:08 +00:00
$languages = language_list ();
unset ( $languages [ 'en' ]);
$output = '' ;
foreach ( $languages as $langcode => $language ) {
2007-09-01 12:50:47 +00:00
if ( ! $limit_language || $limit_language == $langcode ) {
2008-04-14 17:48:46 +00:00
$output .= ( ! empty ( $translation [ $langcode ])) ? $langcode . ' ' : " <em class= \" locale-untranslated \" > $langcode </em> " ;
2007-09-01 12:50:47 +00:00
}
2007-05-03 09:51:08 +00:00
}
return $output ;
}
/**
* @ } End of " locale-api-seek "
*/
/**
* @ defgroup locale - api - predefined List of predefined languages
* @ {
*/
2004-08-11 11:26:20 +00:00
/**
* Prepares the language code list for a select form item with only the unsupported ones
*/
2007-03-26 01:32:22 +00:00
function _locale_prepare_predefined_list () {
$languages = language_list ();
$predefined = _locale_get_predefined_list ();
foreach ( $predefined as $key => $value ) {
if ( isset ( $languages [ $key ])) {
unset ( $predefined [ $key ]);
2004-08-11 11:26:20 +00:00
continue ;
}
2007-03-26 01:32:22 +00:00
// Include native name in output, if possible
2007-08-04 13:08:17 +00:00
if ( count ( $value ) > 1 ) {
2004-08-11 11:26:20 +00:00
$tname = t ( $value [ 0 ]);
2007-03-26 01:32:22 +00:00
$predefined [ $key ] = ( $tname == $value [ 1 ]) ? $tname : " $tname ( $value[1] ) " ;
2004-08-11 11:26:20 +00:00
}
else {
2007-03-26 01:32:22 +00:00
$predefined [ $key ] = t ( $value [ 0 ]);
2004-08-11 11:26:20 +00:00
}
}
2007-03-26 01:32:22 +00:00
asort ( $predefined );
return $predefined ;
2004-08-11 11:26:20 +00:00
}
/**
* Some of the common languages with their English and native names
*
* Based on ISO 639 and http :// people . w3 . org / rishida / names / languages . html
*/
2007-03-26 01:32:22 +00:00
function _locale_get_predefined_list () {
2004-08-11 11:26:20 +00:00
return array (
" aa " => array ( " Afar " ),
" ab " => array ( " Abkhazian " , " аҧсуа бызшәа " ),
" ae " => array ( " Avestan " ),
" af " => array ( " Afrikaans " ),
" ak " => array ( " Akan " ),
" am " => array ( " Amharic " , " አማርኛ " ),
2007-05-15 15:29:49 +00:00
" ar " => array ( " Arabic " , /* Left-to-right marker " " */ " العربية " , LANGUAGE_RTL ),
2004-08-11 11:26:20 +00:00
" as " => array ( " Assamese " ),
" av " => array ( " Avar " ),
" ay " => array ( " Aymara " ),
" az " => array ( " Azerbaijani " , " azərbaycan " ),
" ba " => array ( " Bashkir " ),
" be " => array ( " Belarusian " , " Беларуская " ),
" bg " => array ( " Bulgarian " , " Български " ),
" bh " => array ( " Bihari " ),
" bi " => array ( " Bislama " ),
" bm " => array ( " Bambara " , " Bamanankan " ),
" bn " => array ( " Bengali " ),
" bo " => array ( " Tibetan " ),
" br " => array ( " Breton " ),
" bs " => array ( " Bosnian " , " Bosanski " ),
" ca " => array ( " Catalan " , " Català " ),
" ce " => array ( " Chechen " ),
" ch " => array ( " Chamorro " ),
" co " => array ( " Corsican " ),
" cr " => array ( " Cree " ),
" cs " => array ( " Czech " , " Čeština " ),
" cu " => array ( " Old Slavonic " ),
2006-08-11 17:51:20 +00:00
" cv " => array ( " Chuvash " ),
" cy " => array ( " Welsh " , " Cymraeg " ),
2006-04-19 13:22:12 +00:00
" da " => array ( " Danish " , " Dansk " ),
2004-08-11 11:26:20 +00:00
" de " => array ( " German " , " Deutsch " ),
" dv " => array ( " Maldivian " ),
" dz " => array ( " Bhutani " ),
" ee " => array ( " Ewe " , " Ɛʋɛ " ),
" el " => array ( " Greek " , " Ελληνικά " ),
" en " => array ( " English " ),
" eo " => array ( " Esperanto " ),
" es " => array ( " Spanish " , " Español " ),
" et " => array ( " Estonian " , " Eesti " ),
" eu " => array ( " Basque " , " Euskera " ),
2007-05-15 15:29:49 +00:00
" fa " => array ( " Persian " , /* Left-to-right marker " " */ " فارسی " , LANGUAGE_RTL ),
2004-08-11 11:26:20 +00:00
" ff " => array ( " Fulah " , " Fulfulde " ),
" fi " => array ( " Finnish " , " Suomi " ),
" fj " => array ( " Fiji " ),
" fo " => array ( " Faeroese " ),
" fr " => array ( " French " , " Français " ),
" fy " => array ( " Frisian " , " Frysk " ),
" ga " => array ( " Irish " , " Gaeilge " ),
" gd " => array ( " Scots Gaelic " ),
" gl " => array ( " Galician " , " Galego " ),
" gn " => array ( " Guarani " ),
" gu " => array ( " Gujarati " ),
" gv " => array ( " Manx " ),
" ha " => array ( " Hausa " ),
2007-05-15 15:29:49 +00:00
" he " => array ( " Hebrew " , /* Left-to-right marker " " */ " עברית " , LANGUAGE_RTL ),
2004-08-11 11:26:20 +00:00
" hi " => array ( " Hindi " , " हिन्दी " ),
" ho " => array ( " Hiri Motu " ),
" hr " => array ( " Croatian " , " Hrvatski " ),
" hu " => array ( " Hungarian " , " Magyar " ),
" hy " => array ( " Armenian " , " Հայերեն " ),
" hz " => array ( " Herero " ),
" ia " => array ( " Interlingua " ),
" id " => array ( " Indonesian " , " Bahasa Indonesia " ),
" ie " => array ( " Interlingue " ),
" ig " => array ( " Igbo " ),
" ik " => array ( " Inupiak " ),
" is " => array ( " Icelandic " , " Íslenska " ),
" it " => array ( " Italian " , " Italiano " ),
" iu " => array ( " Inuktitut " ),
" ja " => array ( " Japanese " , " 日本語 " ),
" jv " => array ( " Javanese " ),
" ka " => array ( " Georgian " ),
" kg " => array ( " Kongo " ),
" ki " => array ( " Kikuyu " ),
" kj " => array ( " Kwanyama " ),
" kk " => array ( " Kazakh " , " Қазақ " ),
" kl " => array ( " Greenlandic " ),
" km " => array ( " Cambodian " ),
" kn " => array ( " Kannada " , " ಕನ್ನಡ " ),
" ko " => array ( " Korean " , " 한국어 " ),
" kr " => array ( " Kanuri " ),
" ks " => array ( " Kashmiri " ),
" ku " => array ( " Kurdish " , " Kurdî " ),
" kv " => array ( " Komi " ),
" kw " => array ( " Cornish " ),
" ky " => array ( " Kirghiz " , " Кыргыз " ),
" la " => array ( " Latin " , " Latina " ),
" lb " => array ( " Luxembourgish " ),
" lg " => array ( " Luganda " ),
" ln " => array ( " Lingala " ),
" lo " => array ( " Laothian " ),
2008-01-09 21:36:13 +00:00
" lt " => array ( " Lithuanian " , " Lietuvių " ),
2004-08-11 11:26:20 +00:00
" lv " => array ( " Latvian " , " Latviešu " ),
" mg " => array ( " Malagasy " ),
" mh " => array ( " Marshallese " ),
" mi " => array ( " Maori " ),
" mk " => array ( " Macedonian " , " Македонски " ),
" ml " => array ( " Malayalam " , " മലയാളം " ),
" mn " => array ( " Mongolian " ),
" mo " => array ( " Moldavian " ),
" mr " => array ( " Marathi " ),
" ms " => array ( " Malay " , " Bahasa Melayu " ),
" mt " => array ( " Maltese " , " Malti " ),
" my " => array ( " Burmese " ),
" na " => array ( " Nauru " ),
" nd " => array ( " North Ndebele " ),
" ne " => array ( " Nepali " ),
" ng " => array ( " Ndonga " ),
" nl " => array ( " Dutch " , " Nederlands " ),
2007-03-24 19:07:34 +00:00
" nb " => array ( " Norwegian Bokmål " , " Bokmål " ),
" nn " => array ( " Norwegian Nynorsk " , " Nynorsk " ),
2004-08-11 11:26:20 +00:00
" nr " => array ( " South Ndebele " ),
" nv " => array ( " Navajo " ),
" ny " => array ( " Chichewa " ),
" oc " => array ( " Occitan " ),
" om " => array ( " Oromo " ),
" or " => array ( " Oriya " ),
" os " => array ( " Ossetian " ),
" pa " => array ( " Punjabi " ),
" pi " => array ( " Pali " ),
" pl " => array ( " Polish " , " Polski " ),
2007-05-15 15:29:49 +00:00
" ps " => array ( " Pashto " , /* Left-to-right marker " " */ " پښتو " , LANGUAGE_RTL ),
2006-12-07 17:10:29 +00:00
" pt " => array ( " Portuguese, Portugal " , " Português " ),
" pt-br " => array ( " Portuguese, Brazil " , " Português " ),
2004-08-11 11:26:20 +00:00
" qu " => array ( " Quechua " ),
" rm " => array ( " Rhaeto-Romance " ),
" rn " => array ( " Kirundi " ),
" ro " => array ( " Romanian " , " Română " ),
" ru " => array ( " Russian " , " Русский " ),
" rw " => array ( " Kinyarwanda " ),
" sa " => array ( " Sanskrit " ),
" sc " => array ( " Sardinian " ),
" sd " => array ( " Sindhi " ),
" se " => array ( " Northern Sami " ),
" sg " => array ( " Sango " ),
" sh " => array ( " Serbo-Croatian " ),
" si " => array ( " Singhalese " ),
" sk " => array ( " Slovak " , " Slovenčina " ),
" sl " => array ( " Slovenian " , " Slovenščina " ),
" sm " => array ( " Samoan " ),
" sn " => array ( " Shona " ),
" so " => array ( " Somali " ),
" sq " => array ( " Albanian " , " Shqip " ),
" sr " => array ( " Serbian " , " Српски " ),
" ss " => array ( " Siswati " ),
" st " => array ( " Sesotho " ),
" su " => array ( " Sudanese " ),
" sv " => array ( " Swedish " , " Svenska " ),
" sw " => array ( " Swahili " , " Kiswahili " ),
" ta " => array ( " Tamil " , " தமிழ் " ),
" te " => array ( " Telugu " , " తెలుగు " ),
" tg " => array ( " Tajik " ),
" th " => array ( " Thai " , " ภาษาไทย " ),
" ti " => array ( " Tigrinya " ),
" tk " => array ( " Turkmen " ),
" tl " => array ( " Tagalog " ),
" tn " => array ( " Setswana " ),
" to " => array ( " Tonga " ),
" tr " => array ( " Turkish " , " Türkçe " ),
" ts " => array ( " Tsonga " ),
" tt " => array ( " Tatar " , " Tatarça " ),
" tw " => array ( " Twi " ),
" ty " => array ( " Tahitian " ),
" ug " => array ( " Uighur " ),
" uk " => array ( " Ukrainian " , " Українська " ),
2007-05-15 15:29:49 +00:00
" ur " => array ( " Urdu " , /* Left-to-right marker " " */ " اردو " , LANGUAGE_RTL ),
2004-08-11 11:26:20 +00:00
" uz " => array ( " Uzbek " , " o'zbek " ),
" ve " => array ( " Venda " ),
" vi " => array ( " Vietnamese " , " Tiếng Việt " ),
" wo " => array ( " Wolof " ),
" xh " => array ( " Xhosa " , " isiXhosa " ),
" yi " => array ( " Yiddish " ),
" yo " => array ( " Yoruba " , " Yorùbá " ),
" za " => array ( " Zhuang " ),
2004-09-09 11:53:56 +00:00
" zh-hans " => array ( " Chinese, Simplified " , " 简体中文 " ),
" zh-hant " => array ( " Chinese, Traditional " , " 繁體中文 " ),
2004-08-11 11:26:20 +00:00
" zu " => array ( " Zulu " , " isiZulu " ),
);
}
2007-05-03 09:51:08 +00:00
/**
* @ } End of " locale-api-languages-predefined "
*/
2007-05-15 15:29:49 +00:00
/**
* @ defgroup locale - autoimport Automatic interface translation import
* @ {
*/
/**
2007-05-22 07:42:37 +00:00
* Prepare a batch to import translations for all enabled
* modules in a given language .
2007-05-15 15:29:49 +00:00
*
* @ param $langcode
* Language code to import translations for .
2007-05-22 07:42:37 +00:00
* @ param $finished
* Optional finished callback for the batch .
2007-11-19 13:56:14 +00:00
* @ param $skip
* Array of component names to skip . Used in the installer for the
* second pass import , when most components are already imported .
2007-05-15 15:29:49 +00:00
* @ return
* A batch structure or FALSE if no files found .
*/
2007-11-19 13:56:14 +00:00
function locale_batch_by_language ( $langcode , $finished = NULL , $skip = array ()) {
2007-05-15 15:29:49 +00:00
// Collect all files to import for all enabled modules and themes.
$files = array ();
2007-11-19 13:56:14 +00:00
$components = array ();
$query = " SELECT name, filename FROM { system} WHERE status = 1 " ;
if ( count ( $skip )) {
2008-04-14 17:48:46 +00:00
$query .= " AND name NOT IN ( " . db_placeholders ( $skip , 'varchar' ) . " ) " ;
2007-11-19 13:56:14 +00:00
}
$result = db_query ( $query , $skip );
2007-05-15 15:29:49 +00:00
while ( $component = db_fetch_object ( $result )) {
// Collect all files for all components, names as $langcode.po or
// with names ending with $langcode.po. This allows for filenames
// like node-module.de.po to let translators use small files and
// be able to import in smaller chunks.
2008-04-14 17:48:46 +00:00
$files = array_merge ( $files , file_scan_directory ( dirname ( $component -> filename ) . '/translations' , '(^|\.)' . $langcode . '\.po$' , array ( '.' , '..' , 'CVS' ), 0 , FALSE ));
2007-11-19 13:56:14 +00:00
$components [] = $component -> name ;
2007-05-15 15:29:49 +00:00
}
2007-11-19 13:56:14 +00:00
return _locale_batch_build ( $files , $finished , $components );
2007-05-15 15:29:49 +00:00
}
2007-10-15 15:18:39 +00:00
/**
* Prepare a batch to run when installing modules or enabling themes .
* This batch will import translations for the newly added components
* in all the languages already set up on the site .
*
* @ param $components
* An array of component ( theme and / or module ) names to import
* translations for .
* @ param $finished
* Optional finished callback for the batch .
*/
function locale_batch_by_component ( $components , $finished = '_locale_batch_system_finished' ) {
$files = array ();
$languages = language_list ( 'enabled' );
unset ( $languages [ 1 ][ 'en' ]);
if ( count ( $languages [ 1 ])) {
$language_list = join ( '|' , array_keys ( $languages [ 1 ]));
// Collect all files to import for all $components.
$result = db_query ( " SELECT name, filename FROM { system} WHERE status = 1 " );
while ( $component = db_fetch_object ( $result )) {
if ( in_array ( $component -> name , $components )) {
// Collect all files for this component in all enabled languages, named
// as $langcode.po or with names ending with $langcode.po. This allows
// for filenames like node-module.de.po to let translators use small
// files and be able to import in smaller chunks.
2008-04-14 17:48:46 +00:00
$files = array_merge ( $files , file_scan_directory ( dirname ( $component -> filename ) . '/translations' , '(^|\.)(' . $language_list . ')\.po$' , array ( '.' , '..' , 'CVS' ), 0 , FALSE ));
2007-10-15 15:18:39 +00:00
}
}
return _locale_batch_build ( $files , $finished );
}
return FALSE ;
}
2007-05-15 15:29:49 +00:00
/**
* Build a locale batch from an array of files .
*
2007-05-21 10:56:05 +00:00
* @ param $files
* Array of files to import
2007-05-15 15:29:49 +00:00
* @ param $finished
2007-05-22 07:42:37 +00:00
* Optional finished callback for the batch .
2007-11-19 13:56:14 +00:00
* @ param $components
* Optional list of component names the batch covers . Used in the installer .
2007-05-15 15:29:49 +00:00
* @ return
* A batch structure
*/
2007-11-19 13:56:14 +00:00
function _locale_batch_build ( $files , $finished = NULL , $components = array ()) {
2007-05-15 15:29:49 +00:00
$t = get_t ();
2007-05-21 10:56:05 +00:00
if ( count ( $files )) {
$operations = array ();
2007-09-04 21:10:45 +00:00
foreach ( $files as $file ) {
2007-05-21 10:56:05 +00:00
// We call _locale_batch_import for every batch operation.
$operations [] = array ( '_locale_batch_import' , array ( $file -> filename )); }
$batch = array (
'operations' => $operations ,
'title' => $t ( 'Importing interface translations' ),
'init_message' => $t ( 'Starting import' ),
'error_message' => $t ( 'Error importing interface translations' ),
2007-10-15 15:18:39 +00:00
'file' => './includes/locale.inc' ,
2007-11-19 13:56:14 +00:00
// This is not a batch API construct, but data passed along to the
// installer, so we know what did we import already.
'#components' => $components ,
2007-05-21 10:56:05 +00:00
);
if ( isset ( $finished )) {
$batch [ 'finished' ] = $finished ;
}
2007-05-15 15:29:49 +00:00
return $batch ;
}
return FALSE ;
}
/**
2007-10-15 15:18:39 +00:00
* Perform interface translation import as a batch step .
*
* @ param $filepath
* Path to a file to import .
* @ param $results
* Contains a list of files imported .
*/
function _locale_batch_import ( $filepath , & $context ) {
// The filename is either {langcode}.po or {prefix}.{langcode}.po, so
// we can extract the language code to use for the import from the end.
if ( preg_match ( '!(/|\.)([^\./]+)\.po$!' , $filepath , $langcode )) {
$file = ( object ) array ( 'filename' => basename ( $filepath ), 'filepath' => $filepath );
_locale_import_read_po ( 'db-store' , $file , LOCALE_IMPORT_KEEP , $langcode [ 2 ]);
$context [ 'results' ][] = $filepath ;
}
}
/**
* Finished callback of system page locale import batch .
* Inform the user of translation files imported .
2007-05-15 15:29:49 +00:00
*/
2007-10-15 15:18:39 +00:00
function _locale_batch_system_finished ( $success , $results ) {
if ( $success ) {
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.' ));
}
2007-05-15 15:29:49 +00:00
}
2007-05-21 10:56:05 +00:00
/**
2007-10-15 15:18:39 +00:00
* Finished callback of language addition locale import batch .
* Inform the user of translation files imported .
2007-05-21 10:56:05 +00:00
*/
2007-10-15 15:18:39 +00:00
function _locale_batch_language_finished ( $success , $results ) {
if ( $success ) {
drupal_set_message ( format_plural ( count ( $results ), 'One translation file imported for the enabled modules.' , '@count translation files imported for the enabled modules.' ));
2007-05-21 10:56:05 +00:00
}
}
2007-10-15 15:18:39 +00:00
2007-05-15 15:29:49 +00:00
/**
* @ } End of " locale-autoimport "
*/