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
2004-08-21 06:42:38 +00:00
* Admin - related functions for locale . module .
2004-08-11 11:26:20 +00:00
*/
// ---------------------------------------------------------------------------------
// Language addition functionality (administration only)
/**
* Helper function to add a language
*/
function _locale_add_language ( $code , $name , $onlylanguage = TRUE ) {
db_query ( " INSERT INTO { locales_meta} (locale, name) VALUES ('%s','%s') " , $code , $name );
$result = db_query ( " SELECT lid FROM { locales_source} " );
while ( $string = db_fetch_object ( $result )) {
db_query ( " INSERT INTO { locales_target} (lid, locale) VALUES (%d,'%s') " , $string -> lid , $code );
}
2004-08-12 18:00:11 +00:00
2004-08-11 11:26:20 +00:00
// If only the language was added, and not a PO file import triggered
// the language addition, we need to inform the user on how to start
// a translation
if ( $onlylanguage ) {
2005-03-31 09:25:33 +00:00
$message = t ( '%locale language added. You can now import a translation. See the <a href="%locale-help">help screen</a> for more information.' , array ( '%locale' => theme ( 'placeholder' , t ( $name )), '%locale-help' => url ( 'admin/help/locale' )));
2004-08-11 11:26:20 +00:00
}
else {
2005-03-31 09:25:33 +00:00
$message = t ( '%locale language added.' , array ( '%locale' => theme ( 'placeholder' , t ( $name ))));
2004-08-11 11:26:20 +00:00
}
2004-08-12 18:00:11 +00:00
2004-08-11 11:26:20 +00:00
drupal_set_message ( $message );
2005-03-31 09:25:33 +00:00
watchdog ( 'locale' , t ( '%language language (%locale) added.' , array ( '%language' => theme ( 'placeholder' , $name ), '%locale' => theme ( 'placeholder' , $code ))));
2004-08-11 11:26:20 +00:00
}
/**
* User interface for the language management screen
*/
function _locale_admin_manage_screen () {
$edit = & $_POST [ 'edit' ];
$languages = locale_supported_languages ( TRUE , TRUE );
2004-08-20 14:36:07 +00:00
$header = array ( array ( 'data' => t ( 'Code' )), array ( 'data' => t ( 'English name' )), array ( 'data' => t ( 'Enabled' )), array ( 'data' => t ( 'Default' )), array ( 'data' => t ( 'Translated' )), array ( 'data' => t ( 'Operations' )));
2004-08-11 11:26:20 +00:00
foreach ( $languages [ 'name' ] as $key => $lang ) {
$status = db_fetch_object ( db_query ( " SELECT isdefault, enabled FROM { locales_meta} WHERE locale = '%s' " , $key ));
2004-08-12 18:00:11 +00:00
2004-08-11 11:26:20 +00:00
if ( $key == 'en' ) {
2005-03-31 09:25:33 +00:00
$rows [] = array ( 'en' , check_plain ( $lang ), form_checkbox ( '' , 'enabled][en' , 1 , $status -> enabled ), form_radio ( '' , 'sitedefault' , $key , $status -> isdefault ), message_na (), '' );
2004-08-11 11:26:20 +00:00
}
else {
$original = db_fetch_object ( db_query ( " SELECT COUNT(*) AS strings FROM { locales_source} " ));
$translation = db_fetch_object ( db_query ( " SELECT COUNT(*) AS translation FROM { locales_target} WHERE locale = '%s' AND translation != '' " , $key ));
2004-08-12 18:00:11 +00:00
2004-08-11 11:26:20 +00:00
$ratio = ( $original -> strings > 0 && $translation -> translation > 0 ) ? round (( $translation -> translation / $original -> strings ) * 100. , 2 ) : 0 ;
2004-08-12 18:00:11 +00:00
2005-03-31 09:25:33 +00:00
$rows [] = array ( check_plain ( $key ), ( $key != 'en' ? form_textfield ( '' , 'name][' . $key , $lang , 15 , 64 ) : $lang ), form_checkbox ( '' , 'enabled][' . $key , 1 , $status -> enabled ), form_radio ( '' , 'sitedefault' , $key , $status -> isdefault ), " $translation->translation / $original->strings ( $ratio %) " , ( $key != 'en' ? l ( t ( 'delete' ), 'admin/locale/language/delete/' . urlencode ( $key )) : '' ));
2004-08-11 11:26:20 +00:00
}
}
2004-08-12 18:00:11 +00:00
2004-08-11 11:26:20 +00:00
return form ( theme ( 'table' , $header , $rows ) . form_submit ( t ( 'Save configuration' )), 'POST' , url ( 'admin/locale' ));
}
/**
* User interface for the language addition screen
*/
function _locale_admin_manage_add_screen () {
2004-08-12 18:00:11 +00:00
2004-08-11 11:26:20 +00:00
$isocodes = _locale_prepare_iso_list ();
2004-08-12 18:00:11 +00:00
2004-08-11 11:26:20 +00:00
$output = '<h2>' . t ( 'From language list' ) . '</h2>' ;
$form = form_select ( t ( 'Language name' ), 'langcode' , key ( $isocodes ), $isocodes , t ( 'Select your language here, or add it below, if you are unable to find it.' ));
$form .= form_submit ( t ( 'Add language' ));
$output .= form ( $form );
2004-08-12 18:00:11 +00:00
2004-08-11 11:26:20 +00:00
$edit = & $_POST [ 'edit' ];
$output .= '<h2>' . t ( 'Custom language' ) . '</h2>' ;
2004-10-11 19:57:42 +00:00
$form = form_textfield ( t ( 'Language code' ), 'langcode' , $edit [ 'langcode' ], 70 , 12 , t ( " Commonly this is an <a href= \" %iso-codes \" >ISO 639 language code</a> with an optional country code for regional variants. Examples include 'en', 'en-US' and 'zh-cn'. " , array ( '%iso-codes' => 'http://www.w3.org/WAI/ER/IG/ert/iso639.htm' )));
2004-10-19 18:02:31 +00:00
$form .= form_textfield ( t ( 'Language name in English' ), 'langname' , $edit [ 'langname' ], 70 , 64 , t ( 'Name of the language. Will be available for translation in all languages.' ));
2004-08-11 11:26:20 +00:00
$form .= form_submit ( t ( 'Add language' ));
$output .= form ( $form );
return $output ;
}
/**
* User interface for the translation import screen
*/
function _locale_admin_import_screen () {
$languages = locale_supported_languages ( FALSE , TRUE );
$languages = array_map ( " t " , $languages [ 'name' ]);
unset ( $languages [ 'en' ]);
2004-08-12 18:00:11 +00:00
2004-08-11 11:26:20 +00:00
if ( ! count ( $languages )) {
2004-08-21 21:13:29 +00:00
$languages = _locale_prepare_iso_list ();
2004-08-11 11:26:20 +00:00
}
else {
$languages = array (
t ( 'Already added languages' ) => $languages ,
t ( 'Languages not yet added' ) => _locale_prepare_iso_list ()
);
}
2004-08-21 21:13:29 +00:00
$form = form_file ( t ( 'Language file' ), 'file' , 50 , t ( 'A gettext Portable Object (.po) file.' ));
$form .= form_select ( t ( 'Import into' ), 'langcode' , '' , $languages , t ( 'Choose the language you want to add strings into. If you choose a language which is not yet set up, then it will be added.' ));
2004-10-11 19:57:42 +00:00
$form .= form_radios ( t ( 'Mode' ), 'mode' , 'overwrite' , array ( 'overwrite' => t ( 'Strings in the uploaded file replace existing ones, new ones are added' ), 'keep' => t ( 'Existing strings are kept, only new strings are added' )));
2004-08-21 21:13:29 +00:00
$form .= form_submit ( t ( 'Import' ));
$output = form ( $form , 'POST' , url ( 'admin/locale/language/import' ), array ( 'enctype' => 'multipart/form-data' ));
2004-08-11 11:26:20 +00:00
return $output ;
}
/**
* Parses Gettext Portable Object file information and inserts into database
*
2004-10-26 17:20:58 +00:00
* @ param $file Object contains properties of local file to be imported
2004-08-11 11:26:20 +00:00
* @ param $edit Language code
2004-08-12 18:00:11 +00:00
* @ param $mode should existing translations be replaced ?
2004-08-11 11:26:20 +00:00
*/
function _locale_import_po ( $file , $lang , $mode ) {
2004-08-21 21:13:29 +00:00
// If not in 'safe mode', increase the maximum execution time:
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
2004-08-11 11:26:20 +00:00
// Check if we have the language already in the database
if ( ! db_fetch_object ( db_query ( " SELECT locale FROM { locales_meta} WHERE locale = '%s' " , $lang ))) {
2004-08-18 19:57:27 +00:00
drupal_set_message ( t ( 'Unsupported language selected for import.' ), 'error' );
2004-08-11 11:26:20 +00:00
return FALSE ;
}
2004-08-12 18:00:11 +00:00
2004-08-11 11:26:20 +00:00
// Check if we can get the strings from the file
if ( ! ( $strings = _locale_import_read_po ( $file ))) {
2005-03-31 09:25:33 +00:00
drupal_set_message ( t ( 'Translation file %filename broken: Could not be read.' , array ( '%filename' => theme ( 'placeholder' , $file -> filename ))), 'error' );
2004-08-11 11:26:20 +00:00
return FALSE ;
}
2004-08-12 18:00:11 +00:00
2004-08-11 11:26:20 +00:00
// Strip out header from the string pairs
$header = $strings [ " " ][ " msgstr " ];
unset ( $strings [ " " ]);
2004-08-12 18:00:11 +00:00
2004-08-11 11:26:20 +00:00
// Get information from the header into the database
if ( $header ) {
$hdr = _locale_import_parse_header ( $header );
2004-08-12 18:00:11 +00:00
2004-08-11 11:26:20 +00:00
// Get the plural formula
2004-10-26 17:20:58 +00:00
if ( $hdr [ " Plural-Forms " ] && $p = _locale_import_parse_plural_forms ( $hdr [ " Plural-Forms " ], $file -> filename )) {
2004-08-11 11:26:20 +00:00
list ( $nplurals , $plural ) = $p ;
db_query ( " UPDATE { locales_meta} SET plurals = '%d', formula = '%s' WHERE locale = '%s' " , $nplurals , $plural , $lang );
}
else {
db_query ( " UPDATE { locales_meta} SET plurals = '%d', formula = '%s' WHERE locale = '%s' " , 0 , '' , $lang );
}
}
else {
2005-03-31 09:25:33 +00:00
drupal_set_message ( t ( 'Translation file %filename broken: No header.' , array ( '%filename' => theme ( 'placeholder' , $file -> filename ))), 'error' );
2004-08-11 11:26:20 +00:00
return FALSE ;
}
2004-09-15 15:44:56 +00:00
$additions = 0 ;
$updates = 0 ;
2004-08-11 11:26:20 +00:00
foreach ( $strings as $value ) {
$comments = _locale_import_shorten_comments ( $value [ '#' ]);
2004-08-12 18:00:11 +00:00
2004-08-11 11:26:20 +00:00
// Handle a translation for some plural string
if ( strpos ( $value [ 'msgid' ], " \0 " )) {
$english = explode ( " \0 " , $value [ 'msgid' ], 2 );
$entries = array_keys ( $value [ 'msgstr' ]);
for ( $i = 3 ; $i <= count ( $entries ); $i ++ ) {
$english [] = $english [ 1 ];
}
2004-09-16 14:18:00 +00:00
$translation = array_map ( '_locale_import_append_plural' , $value [ 'msgstr' ], $entries );
$english = array_map ( '_locale_import_append_plural' , $english , $entries );
2004-08-11 11:26:20 +00:00
foreach ( $translation as $key => $trans ) {
2004-09-16 14:18:00 +00:00
if ( $key == 0 ) {
$plid = 0 ;
}
$loc = db_fetch_object ( db_query ( " SELECT lid FROM { locales_source} WHERE source = '%s' " , $english [ $key ]));
if ( $loc -> lid ) { // a string exists
2004-08-11 11:26:20 +00:00
$lid = $loc -> lid ;
2004-09-15 15:44:56 +00:00
// update location field
2004-08-11 11:26:20 +00:00
db_query ( " UPDATE { locales_source} SET location = '%s' WHERE lid = %d " , $comments , $lid );
2004-09-16 14:18:00 +00:00
$trans2 = db_fetch_object ( db_query ( " SELECT lid, translation, plid, plural FROM { locales_target} WHERE lid = %d AND locale = '%s' " , $lid , $lang ));
if ( ! $trans2 -> lid ) { // no translation in current language
db_query ( " INSERT INTO { locales_target} (lid, locale, translation, plid, plural) VALUES (%d, '%s', '%s', %d, %d) " , $lid , $lang , $trans , $plid , $key );
$additions ++ ;
} // translation exists
2004-10-16 01:00:23 +00:00
else if ( $mode == 'overwrite' || $trans2 -> translation == '' ) {
db_query ( " UPDATE { locales_target} SET translation = '%s', plid = %d, plural = %d WHERE locale = '%s' AND lid = %d " , $trans , $plid , $key , $lang , $lid );
2004-09-16 14:18:00 +00:00
if ( $trans2 -> translation == '' ) {
$additions ++ ;
}
else {
$updates ++ ;
}
2004-09-15 15:44:56 +00:00
}
2004-08-11 11:26:20 +00:00
}
2004-09-16 14:18:00 +00:00
else { // no string
2004-10-16 01:00:23 +00:00
db_query ( " INSERT INTO { locales_source} (location, source) VALUES ('%s', '%s') " , $comments , $english [ $key ]);
$loc = db_fetch_object ( db_query ( " SELECT lid FROM { locales_source} WHERE source = '%s' " , $english [ $key ]));
2004-09-16 14:18:00 +00:00
$lid = $loc -> lid ;
2004-09-19 00:08:50 +00:00
db_query ( " INSERT INTO { locales_target} (lid, locale, translation, plid, plural) VALUES (%d, '%s', '%s', %d, %d) " , $lid , $lang , $trans , $plid , $key );
2004-09-16 14:18:00 +00:00
if ( $trans != '' ) {
$additions ++ ;
}
2004-08-11 11:26:20 +00:00
}
2004-09-16 14:18:00 +00:00
$plid = $lid ;
2004-08-11 11:26:20 +00:00
}
}
2004-08-12 18:00:11 +00:00
2004-08-11 11:26:20 +00:00
// A simple translation
else {
$english = $value [ 'msgid' ];
$translation = $value [ 'msgstr' ];
2004-09-16 14:18:00 +00:00
$loc = db_fetch_object ( db_query ( " SELECT lid FROM { locales_source} WHERE source = '%s' " , $english ));
if ( $loc -> lid ) { // a string exists
2004-08-11 11:26:20 +00:00
$lid = $loc -> lid ;
2004-09-15 15:44:56 +00:00
// update location field
2004-08-11 11:26:20 +00:00
db_query ( " UPDATE { locales_source} SET location = '%s' WHERE source = '%s' " , $comments , $english );
2004-09-16 14:18:00 +00:00
$trans = db_fetch_object ( db_query ( " SELECT lid, translation FROM { locales_target} WHERE lid = %d AND locale = '%s' " , $lid , $lang ));
if ( ! $trans -> lid ) { // no translation in current language
db_query ( " INSERT INTO { locales_target} (lid, locale, translation) VALUES (%d, '%s', '%s') " , $lid , $lang , $translation );
$additions ++ ;
} // translation exists
else if ( $mode == 'overwrite' ) { //overwrite in any case
db_query ( " UPDATE { locales_target} SET translation = '%s' WHERE locale = '%s' AND lid = %d " , $translation , $lang , $lid );
if ( $trans -> translation == '' ) {
$additions ++ ;
}
else {
$updates ++ ;
}
} // overwrite if empty string
else if ( $trans -> translation == '' ) {
db_query ( " UPDATE { locales_target} SET translation = '%s' WHERE locale = '%s' AND lid = %d " , $translation , $lang , $lid );
$additions ++ ;
2004-09-15 15:44:56 +00:00
}
2004-08-11 11:26:20 +00:00
}
2004-09-16 14:18:00 +00:00
else { // no string
db_query ( " INSERT INTO { locales_source} (location, source) VALUES ('%s', '%s') " , $comments , $english );
$loc = db_fetch_object ( db_query ( " SELECT lid FROM { locales_source} WHERE source = '%s' " , $english ));
$lid = $loc -> lid ;
2004-08-11 11:26:20 +00:00
db_query ( " INSERT INTO { locales_target} (lid, locale, translation) VALUES (%d, '%s', '%s') " , $lid , $lang , $translation );
2004-09-16 14:18:00 +00:00
if ( $translation != '' ) {
$additions ++ ;
}
2004-08-11 11:26:20 +00:00
}
}
}
2004-08-12 18:00:11 +00:00
2004-10-19 18:02:31 +00:00
// Successful import
2004-10-06 12:18:03 +00:00
// rebuild locale cache
2004-08-11 11:26:20 +00:00
cache_clear_all ( " locale: $lang " );
2004-10-06 12:18:03 +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
2004-09-15 15:44:56 +00:00
drupal_set_message ( t ( 'Translation successfully imported. %number translated strings added to language, %update strings updated.' , array ( '%number' => $additions , '%update' => $updates )));
2005-03-31 09:25:33 +00:00
watchdog ( 'locale' , t ( 'Imported %file into %locale: %number new strings added and %update updated.' , array ( '%file' => theme ( 'placeholder' , $file -> filename ), '%locale' => theme ( 'placeholder' , $lang ), '%number' => $additions , '%update' => $updates )));
2004-08-11 11:26:20 +00:00
return TRUE ;
}
/**
* Parses Gettext Portable Object file into an array
*
2004-10-26 17:20:58 +00:00
* @ param $file Object with properties of local file to parse
2004-08-11 11:26:20 +00:00
* @ author Jacobo Tarrio
*/
2004-10-26 17:20:58 +00:00
function _locale_import_read_po ( $file ) {
2004-08-11 11:26:20 +00:00
2005-03-31 09:25:33 +00:00
$message = theme ( 'placeholder' , $file -> filename );
2004-10-26 17:20:58 +00:00
$fd = fopen ( $file -> filepath , " rb " );
2004-08-11 11:26:20 +00:00
if ( ! $fd ) {
2005-03-31 09:25:33 +00:00
drupal_set_message ( t ( 'Translation import failed: file %filename cannot be read.' , array ( '%filename' => $message )), 'error' );
2004-08-11 11:26:20 +00:00
return FALSE ;
}
$info = fstat ( $fd );
$len = $info [ " size " ];
$po = fread ( $fd , $len );
fclose ( $fd );
$context = " COMMENT " ; // Parser context: COMMENT, MSGID, MSGID_PLURAL, MSGSTR and MSGSTR_ARR
$current = array (); // Current entry being read
$strings = array (); // List of entries read
$plural = 0 ; // Current plural form
$po = strtr ( $po , array ( " \\ \n " => " " ));
$lines = split ( " \n " , $po );
$lineno = 0 ;
foreach ( $lines as $line ) {
$lineno ++ ;
$line = trim ( $line );
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
$strings [ $current [ " msgid " ]] = $current ;
$current = array ();
$current [ " # " ][] = substr ( $line , 1 );
$context = " COMMENT " ;
}
else { // Parse error
2005-03-31 09:25:33 +00:00
drupal_set_message ( t ( " Translation file %filename broken: expected 'msgstr' in line %line. " , array ( '%filename' => $message , '%line' => $lineno )), 'error' );
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
2005-03-31 09:25:33 +00:00
drupal_set_message ( t ( " Translation file %filename broken: unexpected 'msgid_plural' in line %line. " , array ( '%filename' => $message , '%line' => $lineno )), 'error' );
2004-08-11 11:26:20 +00:00
return FALSE ;
}
$line = trim ( substr ( $line , 12 ));
$quoted = _locale_import_parse_quoted ( $line );
if ( $quoted === false ) {
2005-03-31 09:25:33 +00:00
drupal_set_message ( t ( 'Translation file %filename broken: syntax error in line %line.' , array ( '%filename' => $message , '%line' => $lineno )), 'error' );
2004-08-11 11:26:20 +00:00
return FALSE ;
}
$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
$strings [ $current [ " msgid " ]] = $current ;
$current = array ();
}
elseif ( $context == " MSGID " ) { // Already in this context? Parse error
2005-03-31 09:25:33 +00:00
drupal_set_message ( t ( " Translation file %filename broken: unexpected 'msgid' in line %line. " , array ( '%filename' => $message , '%line' => $lineno )), 'error' );
2004-08-11 11:26:20 +00:00
return FALSE ;
}
$line = trim ( substr ( $line , 5 ));
$quoted = _locale_import_parse_quoted ( $line );
if ( $quoted === false ) {
2005-03-31 09:25:33 +00:00
drupal_set_message ( t ( 'Translation file %filename broken: syntax error in line %line.' , array ( '%filename' => $message , '%line' => $lineno )), 'error' );
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[]
2005-03-31 09:25:33 +00:00
drupal_set_message ( t ( " Translation file %filename broken: unexpected 'msgstr[]' in line %line. " , array ( '%filename' => $message , '%line' => $lineno )), 'error' );
2004-08-11 11:26:20 +00:00
return FALSE ;
}
if ( strpos ( $line , " ] " ) === false ) {
2005-03-31 09:25:33 +00:00
drupal_set_message ( t ( 'Translation file %filename broken: syntax error in line %line.' , array ( '%filename' => $message , '%line' => $lineno )), 'error' );
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 );
if ( $quoted === false ) {
2005-03-31 09:25:33 +00:00
drupal_set_message ( t ( 'Translation file %filename broken: syntax error in line %line.' , array ( '%filename' => $message , '%line' => $lineno )), 'error' );
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
2005-03-31 09:25:33 +00:00
drupal_set_message ( t ( " Translation file %filename broken: unexpected 'msgstr' in line %line. " , array ( '%filename' => $message , '%line' => $lineno )), 'error' );
2004-08-11 11:26:20 +00:00
return FALSE ;
}
$line = trim ( substr ( $line , 6 ));
$quoted = _locale_import_parse_quoted ( $line );
if ( $quoted === false ) {
2005-03-31 09:25:33 +00:00
drupal_set_message ( t ( 'Translation file %filename broken: syntax error in line %line.' , array ( '%filename' => $message , '%line' => $lineno )), 'error' );
2004-08-11 11:26:20 +00:00
return FALSE ;
}
$current [ " msgstr " ] = $quoted ;
$context = " MSGSTR " ;
}
elseif ( $line != " " ) {
$quoted = _locale_import_parse_quoted ( $line );
if ( $quoted === false ) {
2005-03-31 09:25:33 +00:00
drupal_set_message ( t ( 'Translation file %filename broken: syntax error in line %line.' , array ( '%filename' => $message , '%line' => $lineno )), 'error' );
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 {
2005-03-31 09:25:33 +00:00
drupal_set_message ( t ( 'Translation file %filename broken: unexpected string in line %line.' , array ( '%filename' => $message , '%line' => $lineno )), 'error' );
2004-08-11 11:26:20 +00:00
return FALSE ;
}
}
}
// End of PO file, flush last entry
if (( $context == " MSGSTR " ) || ( $context == " MSGSTR_ARR " )) {
$strings [ $current [ " msgid " ]] = $current ;
}
elseif ( $context != " COMMENT " ) {
2005-03-31 09:25:33 +00:00
drupal_set_message ( t ( 'Translation file %filename broken: unexpected end of file at line %line.' , array ( '%filename' => $message , '%line' => $lineno )), 'error' );
2004-08-11 11:26:20 +00:00
return FALSE ;
}
return $strings ;
}
/**
* Parses a Gettext Portable Object file header
*
* @ param $header A string containing the complete header
* @ return An associative array of key - value pairs
* @ author Jacobo Tarrio
*/
function _locale_import_parse_header ( $header ) {
$hdr = array ();
$lines = explode ( " \n " , $header );
foreach ( $lines as $line ) {
$line = trim ( $line );
if ( $line ) {
list ( $tag , $contents ) = explode ( " : " , $line , 2 );
$hdr [ trim ( $tag )] = trim ( $contents );
}
}
return $hdr ;
}
/**
* Parses a Plural - Forms entry from a Gettext Portable Object file header
*
* @ param $pluralforms A string containing the Plural - Forms entry
2004-10-26 17:20:58 +00:00
* @ param $filename A string containing the filename
2004-08-11 11:26:20 +00:00
* @ return An array containing the number of plurals and a
* formula in PHP for computing the plural form
* @ author Jacobo Tarrio
*/
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 );
if ( $plural ) {
return array ( $nplurals , $plural );
}
else {
2005-03-31 09:25:33 +00:00
drupal_set_message ( t ( " Translation file %filename broken: plural formula couldn't get parsed. " , array ( '%filename' => theme ( 'placeholder' , $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 .
*
* @ param $string A string containing the arithmetic formula
* @ return The PHP version of the formula
* @ author Jacobo Tarrio
*/
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 );
while (( $topop != NULL ) && ( $topop != " ( " )) {
$elstk [] = $topop ;
$topop = array_pop ( $opstk );
}
}
elseif ( $prec [ $ctok ]) {
// 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 );
while (( $topop != NULL ) && ( $prec [ $topop ] >= $prec [ $ctok ]) && ! (( $prec [ $topop ] == $prec [ $ctok ]) && $rasc [ $topop ] && $rasc [ $ctok ])) {
$elstk [] = $topop ;
$topop = array_pop ( $opstk );
}
if ( $topop ) {
$opstk [] = $topop ; // Return element to top
}
$opstk [] = $ctok ; // Parentheses are not needed
}
else {
return false ;
}
}
// 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 ];
if ( $prec [ $op ]) {
$f = " " ;
if ( $op == " : " ) {
$f = $elstk [ $i - 2 ] . " ): " . $elstk [ $i - 1 ] . " ) " ;
}
elseif ( $op == " ? " ) {
$f = " ( " . $elstk [ $i - 2 ] . " ?( " . $elstk [ $i - 1 ];
}
else {
$f = " ( " . $elstk [ $i - 2 ] . $op . $elstk [ $i - 1 ] . " ) " ;
}
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
*
* @ param $string A string containing the arithmetic formula
* @ return The PHP version of the formula
* @ author Gerhard Killesreiter
*/
function _locale_import_tokenize_formula ( $formula ) {
$formula = str_replace ( " " , " " , $formula );
$tokens = array ();
for ( $i = 0 ; $i < strlen ( $formula ); $i ++ ) {
if ( is_numeric ( $formula { $i })) {
$num = $formula { $i };
$j = $i + 1 ;
while ( $j < strlen ( $formula ) && is_numeric ( $formula { $j })) {
$num .= $formula { $j };
$j ++ ;
}
$i = $j - 1 ;
$tokens [] = $num ;
}
elseif ( $pos = strpos ( " =<>!&| " , $formula { $i })) { // We won't have a space
$next = $formula {( $i + 1 )};
switch ( $pos ) {
case 1 :
case 2 :
case 3 :
case 4 :
if ( $next == '=' ) {
$tokens [] = $formula { $i } . '=' ;
$i ++ ;
}
else {
$tokens [] = $formula { $i };
}
break ;
case 5 :
if ( $next == '&' ) {
$tokens [] = '&&' ;
$i ++ ;
}
else {
$tokens [] = $formula { $i };
}
break ;
case 6 :
if ( $next == '|' ) {
$tokens [] = '||' ;
$i ++ ;
}
else {
$tokens [] = $formula { $i };
}
break ;
}
}
else {
$tokens [] = $formula { $i };
}
}
return $tokens ;
}
/**
* Modify a string to contain proper count indices
*
* This is a callback function used via array_map ()
*
* @ param $entry An array element
* @ param $key Index of the array element
*/
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
$entry = preg_replace ( '/(%count)\[[0-9]\]/' , '\\1' , $entry );
return preg_replace ( '/(%count)/' , " \\ 1[ $key ] " , $entry );
}
/**
* Generate a short , one string version of the passed comment array
*
* @ param $comment An array of strings containing a comment
* @ return Short one string version of the comment
*/
function _locale_import_shorten_comments ( $comment ) {
$comm = '' ;
while ( strlen ( $comm ) < 128 && count ( $comment )) {
$comm .= substr ( array_shift ( $comment ), 1 ) . ', ' ;
}
return substr ( $comm , 0 , - 2 );
}
/**
* Parses a string in quotes
*
* @ param $string A string specified with enclosing quotes
* @ return The string parsed from inside the quotes
*/
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
}
}
/**
* User interface for the translation export screen
*/
function _locale_admin_export_screen () {
$languages = locale_supported_languages ( FALSE , TRUE );
$languages = array_map ( " t " , $languages [ 'name' ]);
unset ( $languages [ 'en' ]);
$output = '' ;
// Offer language specific export if any language is set up
if ( count ( $languages )) {
$output .= '<h2>' . t ( 'Export translation' ) . '</h2>' ;
$form = form_select ( t ( 'Language name' ), 'langcode' , '' , $languages , t ( 'Select the language you would like to export in gettext Portable Object (.po) format.' ));
$form .= form_submit ( t ( 'Export' ));
$output .= form ( $form );
}
// Complete template export of the strings
$output .= '<h2>' . t ( 'Export template' ) . '</h2>' ;
$form = t ( '<p>Generate a gettext Portable Object Template (.pot) file with all the interface strings from the Drupal locale database.</p>' );
$form .= form_submit ( t ( 'Export' ));
$output .= form ( $form );
2004-08-12 18:00:11 +00:00
2004-08-11 11:26:20 +00:00
return $output ;
}
/**
* Exports a Portable Object ( Template ) file for a language
*
* @ param $language Selects a language to generate the output for
*/
function _locale_export_po ( $language ) {
global $user ;
2004-08-12 18:00:11 +00:00
2004-08-11 11:26:20 +00:00
// Get language specific strings, or all strings
if ( $language ) {
$meta = db_fetch_object ( db_query ( " SELECT * FROM { locales_meta} WHERE locale = '%s' " , $language ));
$result = db_query ( " SELECT s.lid, s.source, s.location, t.translation, t.plid, t.plural FROM { locales_source} s INNER JOIN { locales_target} t ON s.lid = t.lid WHERE t.locale = '%s' ORDER BY t.plid, t.plural " , $language );
}
else {
2005-04-25 17:57:03 +00:00
$result = db_query ( " SELECT s.lid, s.source, s.location, t.plid, t.plural FROM { locales_source} s INNER JOIN { locales_target} t ON s.lid = t.lid ORDER BY t.plid, t.plural " );
2004-08-11 11:26:20 +00:00
}
2004-08-12 18:00:11 +00:00
2004-08-11 11:26:20 +00:00
// Build array out of the database results
$parent = array ();
while ( $child = db_fetch_object ( $result )) {
2004-10-11 19:57:42 +00:00
if ( $child -> source != '' ) {
$parent [ $child -> lid ][ 'comment' ] = $child -> location ;
$parent [ $child -> lid ][ 'msgid' ] = $child -> source ;
if ( $child -> plid ) {
$parent [ $child -> lid ][ $child -> plid ][ 'plural' ] = $child -> lid ;
$parent [ $child -> lid ][ $child -> plid ][ 'translation' ] = $child -> translation ;
$parent [ $child -> lid ][ $child -> plid ][ 'msgid' ] = $child -> source ;
}
else {
$parent [ $child -> lid ][ 'translation' ] = $child -> translation ;
}
2004-08-11 11:26:20 +00:00
}
}
2004-08-12 18:00:11 +00:00
2004-08-11 11:26:20 +00:00
// Generating Portable Object file for a language
if ( $language ) {
$filename = $language . '.po' ;
$header .= " # $meta->name translation of " . variable_get ( 'site_name' , 'Drupal' ) . " \n " ;
$header .= '# Copyright (c) ' . date ( 'Y' ) . ' ' . $user -> name . ' <' . $user -> mail . " > \n " ;
$header .= " # \n " ;
$header .= " msgid \" \" \n " ;
$header .= " msgstr \" \" \n " ;
$header .= " \" Project-Id-Version: PROJECT VERSION \\ n \" \n " ;
$header .= " \" POT-Creation-Date: " . date ( " Y-m-d H:iO " ) . " \\ n \" \n " ;
$header .= " \" PO-Revision-Date: " . date ( " Y-m-d H:iO " ) . " \\ n \" \n " ;
$header .= " \" Last-Translator: " . $user -> name . ' <' . $user -> mail . " > \\ n \" \n " ;
$header .= " \" Language-Team: " . $meta -> name . ' <' . $user -> mail . " > \\ 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 ( $meta -> formula && $meta -> plurals ) {
$header .= " \" Plural-Forms: nplurals= " . $meta -> plurals . " ; plural= " . strtr ( $meta -> formula , '$' , '' ) . " ; \\ n \" \n " ;
}
$header .= " \n " ;
2005-03-31 09:25:33 +00:00
watchdog ( 'locale' , t ( 'Exported %locale translation file: %filename.' , array ( '%locale' => theme ( 'placeholder' , $meta -> name ), '%filename' => theme ( 'placeholder' , $filename ))));
2004-08-11 11:26:20 +00:00
}
2004-08-12 18:00:11 +00:00
2004-08-11 11:26:20 +00:00
// Generating Portable Object Template
else {
$filename = variable_get ( 'site_name' , 'drupal' ) . '.pot' ;
$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 " ;
$header .= " \" POT-Creation-Date: " . date ( " Y-m-d H:iO " ) . " \\ n \" \n " ;
$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 " ;
$header .= " \n " ;
2005-03-31 09:25:33 +00:00
watchdog ( 'locale' , t ( 'Exported translation file: %filename.' , array ( '%filename' => theme ( 'placeholder' , $filename ))));
2004-08-11 11:26:20 +00:00
}
// Start download process
header ( " Content-Disposition: attachment; filename= $filename " );
header ( " Content-Type: text/plain; charset=utf-8 " );
print $header ;
foreach ( $parent as $lid => $message ) {
if ( ! isset ( $done [ $lid ])) {
if ( $message [ 'comment' ]) {
print '#: ' . $message [ 'comment' ] . " \n " ;
}
print 'msgid ' . _locale_export_print ( $message [ 'msgid' ]);
if ( isset ( $message [ 1 ][ 'plural' ])) {
print 'msgid_plural ' . _locale_export_print ( $message [ 1 ][ 'msgid' ]);
if ( $language ) {
for ( $i = 0 ; $i < $meta -> plurals ; $i ++ ) {
print 'msgstr[' . $i . '] ' . _locale_export_print ( _locale_export_remove_plural ( $message [ $ { i }][ 'translation' ]));
$done [ $message [ $ { i }][ 'plural' ]] = 1 ;
}
}
else {
print 'msgstr[0] ""' . " \n " ;
print 'msgstr[1] ""' . " \n " ;
$done [ $message [ 0 ][ 'plural' ]] = 1 ;
$done [ $message [ 1 ][ 'plural' ]] = 1 ;
}
}
else {
if ( $language ) {
print 'msgstr ' . _locale_export_print ( $message [ 'translation' ]);
}
else {
print 'msgstr ""' . " \n " ;
}
}
print " \n " ;
}
}
die ();
}
/**
* Print out a string on multiple lines
*/
function _locale_export_print ( $str ) {
$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 );
}
if ( count ( $parts ) > 1 ) {
return " \" \" \n \" " . implode ( " \" \n \" " , $parts ) . " \" \n " ;
}
else {
return " \" $parts[0] \" \n " ;
}
}
/**
* Custom word wrapping for Portable Object ( Template ) files .
*
* @ author Jacobo Tarrio
*/
function _locale_export_wrap ( $str , $len ) {
$words = split ( " " , $str );
$ret = array ();
$cur = " " ;
$nstr = 1 ;
while ( count ( $words )) {
$word = array_shift ( $words );
if ( $nstr ) {
$cur = $word ;
$nstr = 0 ;
}
elseif ( strlen ( " $cur $word " ) > $len ) {
$ret [] = $cur . " " ;
$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 ) {
return preg_replace ( '/(%count)\[[0-9]\]/' , '\\1' , $entry );
}
function _locale_string_delete ( $lid ) {
2004-10-06 12:18:03 +00:00
db_query ( 'DELETE FROM {locales_source} WHERE lid = %d' , $lid );
db_query ( 'DELETE FROM {locales_target} WHERE lid = %d' , $lid );
2004-08-11 11:26:20 +00:00
locale_refresh_cache ();
2004-10-06 12:18:03 +00:00
drupal_set_message ( t ( 'Deleted string' ));
2004-08-11 11:26:20 +00:00
}
/**
* Action handler for string editing
*
* Saves all translations of one string submitted from a form
*/
function _locale_string_save ( $lid ) {
2004-10-06 12:18:03 +00:00
$edit =& $_POST [ 'edit' ];
2004-08-11 11:26:20 +00:00
foreach ( $edit as $key => $value ) {
$trans = db_fetch_object ( db_query ( " SELECT translation FROM { locales_target} WHERE lid = %d AND locale = '%s' " , $lid , $key ));
2004-09-15 15:44:56 +00:00
if ( isset ( $trans -> translation )) {
2004-08-11 11:26:20 +00:00
db_query ( " UPDATE { locales_target} SET translation = '%s' WHERE lid = %d AND locale = '%s' " , $value , $lid , $key );
}
else {
db_query ( " INSERT INTO { locales_target} (lid, translation, locale) VALUES (%d, '%s', '%s') " , $lid , $value , $key );
}
}
2004-10-06 12:18:03 +00:00
// refresh the locale cache
2004-08-11 11:26:20 +00:00
locale_refresh_cache ();
2004-10-06 12:18:03 +00:00
// rebuild the menu, strings may have changed
menu_rebuild ();
2004-08-11 11:26:20 +00:00
// delete form data so it will remember where it came from
$edit = '' ;
2004-10-06 12:18:03 +00:00
drupal_set_message ( t ( 'Saved string' ));
2004-08-11 11:26:20 +00:00
}
/**
* User interface for string editing
*/
function _locale_string_edit ( $lid ) {
$languages = locale_supported_languages ( FALSE , TRUE );
unset ( $languages [ 'name' ][ 'en' ]);
2004-08-12 18:00:11 +00:00
2004-10-06 12:18:03 +00:00
$result = db_query ( 'SELECT DISTINCT s.source, t.translation, t.locale FROM {locales_source} s INNER JOIN {locales_target} t ON s.lid = t.lid WHERE s.lid = %d' , $lid );
2004-08-11 11:26:20 +00:00
$form = '' ;
while ( $translation = db_fetch_object ( $result )) {
$orig = $translation -> source ;
$form .= ( strlen ( $orig ) > 40 ) ? form_textarea ( $languages [ 'name' ][ $translation -> locale ], $translation -> locale , $translation -> translation , 70 , 15 ) : form_textfield ( $languages [ 'name' ][ $translation -> locale ], $translation -> locale , $translation -> translation , 50 , 128 );
unset ( $languages [ 'name' ][ $translation -> locale ]);
}
foreach ( $languages [ 'name' ] as $key => $lang ) {
$form .= ( strlen ( $orig ) > 40 ) ? form_textarea ( $lang , $key , '' , 70 , 15 ) : form_textfield ( $lang , $key , '' , 50 , 128 );
}
2005-04-02 18:22:17 +00:00
$form = form_item ( t ( 'Original text' ), wordwrap ( check_plain ( $orig , 0 ))) . $form ;
2004-08-11 11:26:20 +00:00
$form .= form_submit ( t ( 'Save translations' ));
return form ( $form );
}
/**
* List languages in search result table
*/
function _locale_string_language_list ( $translation ) {
$languages = locale_supported_languages ( FALSE , TRUE );
unset ( $languages [ 'name' ][ 'en' ]);
$output = '' ;
foreach ( $languages [ 'name' ] as $key => $value ) {
if ( isset ( $translation [ $key ])) {
$output .= ( $translation [ $key ] != '' ) ? $key . ' ' : " <strike> $key </strike> " ;
2004-08-12 18:00:11 +00:00
}
2004-08-11 11:26:20 +00:00
}
return $output ;
}
/**
* Build object out of search criteria specified in request variables
*/
function _locale_string_seek_query () {
static $query = NULL ;
2004-09-20 19:37:18 +00:00
if ( is_null ( $query )) {
2004-08-11 11:26:20 +00:00
$fields = array ( 'string' , 'language' , 'searchin' );
$query = new StdClass ;
if ( is_array ( $_REQUEST [ 'edit' ])) {
foreach ( $_REQUEST [ 'edit' ] as $key => $value ) {
if ( ! empty ( $value ) && in_array ( $key , $fields )) {
$query -> $key = $value ;
}
}
}
else {
foreach ( $_REQUEST as $key => $value ) {
if ( ! empty ( $value ) && in_array ( $key , $fields )) {
$query -> $key = strpos ( ',' , $value ) ? explode ( ',' , $value ) : $value ;
}
}
}
}
return $query ;
}
/**
* Perform a string search and display results in a table
*/
function _locale_string_seek () {
2005-03-31 21:18:08 +00:00
// We have at least one criterion to match
2004-08-11 11:26:20 +00:00
if ( $query = _locale_string_seek_query ()) {
$join = " SELECT s.source, s.location, s.lid, t.translation, t.locale FROM { locales_source} s INNER JOIN { locales_target} t ON s.lid = t.lid " ;
// Compute LIKE section
switch ( $query -> searchin ) {
case 'translated' :
2004-11-21 08:25:17 +00:00
$where = " WHERE (t.translation LIKE '% " . db_escape_string ( $query -> string ) . " %' AND t.translation != '') " ;
2004-08-11 11:26:20 +00:00
$orderby = " ORDER BY t.translation " ;
break ;
case 'untranslated' :
2004-11-21 08:25:17 +00:00
$where = " WHERE (s.source LIKE '% " . db_escape_string ( $query -> string ) . " %' AND t.translation = '') " ;
2004-08-11 11:26:20 +00:00
$orderby = " ORDER BY s.source " ;
break ;
case 'all' :
default :
2004-11-21 08:25:17 +00:00
$where = " WHERE (s.source LIKE '% " . db_escape_string ( $query -> string ) . " %' OR t.translation LIKE '% " . db_escape_string ( $query -> string ) . " %') " ;
2004-08-11 11:26:20 +00:00
$orderby = '' ;
break ;
}
switch ( $query -> language ) {
// Force search in source strings
case " en " :
2004-11-21 08:25:17 +00:00
$sql = $join . " WHERE s.source LIKE '% " . db_escape_string ( $query -> string ) . " %' ORDER BY s.source " ;
2004-08-11 11:26:20 +00:00
break ;
// Search in all languages
case " all " :
$sql = " $join $where $orderby " ;
break ;
// Some different language
default :
2004-11-21 08:25:17 +00:00
$sql = " $join $where AND t.locale = ' " . db_escape_string ( $query -> language ) . " ' $orderby " ;
2004-08-11 11:26:20 +00:00
}
$result = pager_query ( $sql , 50 );
2004-08-19 15:41:57 +00:00
$header = array ( t ( 'String' ), t ( 'Locales' ), array ( 'data' => t ( 'Operations' ), 'colspan' => '2' ));
2004-08-11 11:26:20 +00:00
$arr = array ();
while ( $locale = db_fetch_object ( $result )) {
$arr [ $locale -> lid ][ 'locales' ][ $locale -> locale ] = $locale -> translation ;
$arr [ $locale -> lid ][ 'location' ] = $locale -> location ;
$arr [ $locale -> lid ][ 'source' ] = $locale -> source ;
}
foreach ( $arr as $lid => $value ) {
$source = htmlspecialchars ( $value [ 'source' ]);
$rows [] = array ( array ( 'data' => ( strlen ( $source ) > 150 ? substr ( $source , 0 , 150 ) . '...' : $source ) . '<br /><small>' . $value [ 'location' ] . '</small>' ), array ( 'data' => _locale_string_language_list ( $value [ 'locales' ]), 'align' => 'center' ), array ( 'data' => l ( t ( 'edit' ), " admin/locale/string/edit/ $lid " ), 'nowrap' => 'nowrap' ), array ( 'data' => l ( t ( 'delete' ), " admin/locale/string/delete/ $lid " ), 'nowrap' => 'nowrap' ));
}
$request = array ();
if ( count ( $query )) {
foreach ( $query as $key => $value ) {
$request [ $key ] = ( is_array ( $value )) ? implode ( ',' , $value ) : $value ;
}
}
if ( $pager = theme ( 'pager' , NULL , 50 , 0 , $request )) {
$rows [] = array ( array ( 'data' => " $pager " , 'colspan' => '5' ));
}
$output .= theme ( 'table' , $header , $rows );
}
return $output ;
}
/**
* User interface for the string search screen
*/
function _locale_string_seek_form () {
// Get *all* languages set up
$languages = locale_supported_languages ( FALSE , TRUE );
asort ( $languages [ 'name' ]); unset ( $languages [ 'name' ][ 'en' ]);
2005-03-31 09:25:33 +00:00
$languages [ 'name' ] = array_map ( 'check_plain' , $languages [ 'name' ]);
2004-08-11 11:26:20 +00:00
// Present edit form preserving previous user settings
$query = _locale_string_seek_query ();
$form .= form_textfield ( t ( 'Strings to search for' ), 'string' , $query -> string , 30 , 30 , t ( 'Leave blank to show all strings. The search is case sensitive.' ));
$form .= form_radios ( t ( 'Language' ), 'language' , ( $query -> language ? $query -> language : 'all' ), array_merge ( array ( 'all' => t ( 'All languages' ), 'en' => t ( 'English (provided by Drupal)' )), $languages [ 'name' ]));
$form .= form_radios ( t ( 'Search in' ), 'searchin' , ( $query -> searchin ? $query -> searchin : 'all' ), array ( 'all' => t ( 'All strings in that language' ), 'translated' => t ( 'Only translated strings' ), 'untranslated' => t ( 'Only untranslated strings' )));
$form .= form_submit ( t ( 'Search' ));
$output = form ( form_group ( t ( 'Search strings' ), $form ), 'POST' , url ( 'admin/locale/string/search' ));
return $output ;
}
// ---------------------------------------------------------------------------------
// List of some of the most common languages (administration only)
/**
* Prepares the language code list for a select form item with only the unsupported ones
*/
function _locale_prepare_iso_list () {
$languages = locale_supported_languages ( FALSE , TRUE );
$isocodes = _locale_get_iso639_list ();
foreach ( $isocodes as $key => $value ) {
if ( isset ( $languages [ 'name' ][ $key ])) {
unset ( $isocodes [ $key ]);
continue ;
}
if ( count ( $value ) == 2 ) {
$tname = t ( $value [ 0 ]);
$isocodes [ $key ] = ( $tname == $value [ 1 ]) ? $tname : " $tname ( $value[1] ) " ;
}
else {
$isocodes [ $key ] = t ( $value [ 0 ]);
}
}
asort ( $isocodes );
return $isocodes ;
}
/**
* Some of the common languages with their English and native names
*
* Based on ISO 639 and http :// people . w3 . org / rishida / names / languages . html
*/
function _locale_get_iso639_list () {
return array (
" aa " => array ( " Afar " ),
" ab " => array ( " Abkhazian " , " аҧсуа бызшәа " ),
" ae " => array ( " Avestan " ),
" af " => array ( " Afrikaans " ),
" ak " => array ( " Akan " ),
" am " => array ( " Amharic " , " አማርኛ " ),
" ar " => array ( " Arabic " , " العربية " ),
" 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 " ),
" cv " => array ( " Welsh " , " Cymraeg " ),
" cy " => array ( " Welch " ),
" da " => array ( " Danish " ),
" 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 " ),
" fa " => array ( " Persian " , " فارسی " ),
" 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 " ),
" he " => array ( " Hebrew " , " עברית " ),
" 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 " ),
" lt " => array ( " Lithuanian " , " Lietuviškai " ),
" 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 " ),
" no " => array ( " Norwegian " , " Norsk " ),
" 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 " ),
" ps " => array ( " Pashto " , " پښتو " ),
" pt " => array ( " Portuguese " , " Português " ),
" 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 " , " Українська " ),
" ur " => array ( " Urdu " , " اردو " ),
" uz " => array ( " Uzbek " , " o'zbek " ),
" ve " => array ( " Venda " ),
" vi " => array ( " Vietnamese " , " Tiếng Việt " ),
" vo " => array ( " Volapük " ),
" 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 " ),
);
}
?>