2020-05-06 16:06:05 +02:00
< ? php
/*******************************************************************************
* Copyright ( C ) 2007 Easter - eggs
2021-04-13 18:04:19 +02:00
* https :// ldapsaisie . org
2020-05-06 16:06:05 +02:00
*
* Author : See AUTHORS file in top - level directory .
*
* This program is free software ; you can redistribute it and / or
* modify it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software
* Foundation , Inc . , 59 Temple Place - Suite 330 , Boston , MA 02111 - 1307 , USA .
******************************************************************************/
2020-05-08 13:23:45 +02:00
LSsession :: loadLSclass ( 'LSlog_staticLoggerClass' );
class LSlang extends LSlog_staticLoggerClass {
2020-05-06 16:06:05 +02:00
2022-12-31 21:15:19 +01:00
/**
* Current lang
* @ see LSlang :: setLocale ()
* @ see LSlang :: getLang ()
* @ var string | null
*/
2020-05-06 16:06:05 +02:00
private static $lang = NULL ;
2022-12-31 21:15:19 +01:00
/**
* Current encoding
* @ see LSlang :: setLocale ()
* @ see LSlang :: getEncoding ()
* @ var string | null
*/
2020-05-06 16:06:05 +02:00
private static $encoding = NULL ;
/**
* Define current locale ( and encoding )
*
2022-12-31 05:52:31 +01:00
* @ param string | null $lang The lang ( optional , default : default current LDAP
2020-05-06 16:06:05 +02:00
* server lang , or default lang )
2022-12-31 21:15:19 +01:00
* @ param string | null $encoding The encoding ( optional , default : default current LDAP
2020-05-06 16:06:05 +02:00
* server encoding , or default encoding )
*
2022-12-31 05:52:31 +01:00
* @ return void
2020-05-06 16:06:05 +02:00
*/
public static function setLocale ( $lang = null , $encoding = null ) {
// Handle $lang parameter
if ( is_null ( $lang )) {
if ( isset ( $_REQUEST [ 'lang' ])) {
$lang = $_REQUEST [ 'lang' ];
}
elseif ( isset ( $_SESSION [ 'LSlang' ])) {
$lang = $_SESSION [ 'LSlang' ];
}
elseif ( isset ( LSsession :: $ldapServer [ 'lang' ])) {
$lang = LSsession :: $ldapServer [ 'lang' ];
}
else {
$lang = LSconfig :: get ( 'lang' );
}
}
// Handle $encoding parameter
if ( is_null ( $encoding )) {
if ( isset ( $_REQUEST [ 'encoding' ])) {
$encoding = $_REQUEST [ 'encoding' ];
}
elseif ( isset ( $_SESSION [ 'LSencoding' ])) {
$encoding = $_SESSION [ 'LSencoding' ];
}
elseif ( isset ( LSsession :: $ldapServer [ 'encoding' ])) {
$encoding = LSsession :: $ldapServer [ 'encoding' ];
}
else {
$encoding = LSconfig :: get ( 'encoding' );
}
}
// Set session and self variables
$_SESSION [ 'LSlang' ] = self :: $lang = $lang ;
$_SESSION [ 'LSencoding' ] = self :: $encoding = $encoding ;
// Check
if ( self :: localeExist ( $lang , $encoding )) {
2021-06-29 16:46:50 +02:00
self :: log_trace ( " setLocale( $lang , $encoding ): local ' $lang . $encoding ' exist, use it " );
2020-05-06 16:06:05 +02:00
if ( $encoding ) {
$lang .= '.' . $encoding ;
}
// Gettext firstly look the LANGUAGE env variable, so set it
putenv ( " LANGUAGE= $lang " );
// Set the locale
if ( setlocale ( LC_ALL , $lang ) === false )
2020-05-08 15:16:24 +02:00
self :: log_error ( " An error occured setting locale to ' $lang ' " );
2020-05-06 16:06:05 +02:00
// Configure and set the text domain
$fullpath = bindtextdomain ( LS_TEXT_DOMAIN , LS_I18N_DIR_PATH );
2021-06-29 16:46:50 +02:00
self :: log_trace ( " setLocale( $lang , $encoding ): Text domain fullpath is ' $fullpath '. " );
self :: log_trace ( " setLocale( $lang , $encoding ): Text domain is : " . textdomain ( LS_TEXT_DOMAIN ));
2020-05-06 16:06:05 +02:00
// Include local translation file
2020-05-07 11:35:06 +02:00
$lang_file = LS_I18N_DIR . '/' . $lang . '/lang.php' ;
if ( LSsession :: includeFile ( $lang_file , false , false ))
2021-06-29 16:46:50 +02:00
self :: log_trace ( " setLocale( $lang , $encoding ): lang file ' $lang_file ' loaded. " );
2020-05-07 11:35:06 +02:00
else
2021-06-29 16:46:50 +02:00
self :: log_trace ( " setLocale( $lang , $encoding ): no lang file found ( $lang_file ). " );
2020-05-06 16:06:05 +02:00
// Include other local translation file(s)
2021-06-29 16:46:50 +02:00
foreach ( array ( LS_I18N_DIR_PATH . '/' . $lang , LS_ROOT_DIR . '/' . LS_LOCAL_DIR . '/' . LS_I18N_DIR . '/' . $lang ) as $lang_dir ) {
self :: log_trace ( " setLocale( $lang , $encoding ): lookup for translation file in ' $lang_dir ' " );
2020-05-06 16:06:05 +02:00
if ( is_dir ( $lang_dir )) {
2021-06-29 16:46:50 +02:00
foreach ( listFiles ( $lang_dir , '/^lang\..+\.php$/' ) as $file ) {
2020-05-06 16:06:05 +02:00
$path = " $lang_dir / $file " ;
2021-06-29 16:46:50 +02:00
self :: log_trace ( " setLocale( $lang , $encoding ): load translation file ' $path ' " );
2020-05-06 16:06:05 +02:00
include ( $path );
}
}
}
}
else {
if ( $encoding && $lang ) $lang .= '.' . $encoding ;
2020-05-08 15:16:24 +02:00
self :: log_error ( " The local ' $lang ' does not exists, use default one. " );
2020-05-06 16:06:05 +02:00
}
}
/**
* Return list of available languages
*
2022-12-31 21:15:19 +01:00
* @ param string | null $encoding Specify encoding for lang selection . If null , use self :: encoding value ,
2020-06-15 08:30:50 +02:00
* if false , do not filter on encoding , otherwise filter available lang for
* specified encoding ( optional , default : null )
2022-12-31 21:15:19 +01:00
* @ param bool $with_encoding Return available lang list with encoding ( optional , default : false )
2020-06-15 08:30:50 +02:00
*
2022-12-31 05:52:31 +01:00
* @ return array List of available languages .
2020-05-06 16:06:05 +02:00
**/
2020-06-15 08:30:50 +02:00
public static function getLangList ( $encoding = null , $with_encoding = false ) {
if ( is_null ( $encoding ))
$encoding = self :: $encoding ;
if ( $with_encoding )
$list = array ( 'en_US.UTF8' );
else
$list = array ( 'en_US' );
if ( $encoding ) {
if ( $with_encoding )
$regex = '/^([a-zA-Z_]*\.' . $encoding . ')$/' ;
else
$regex = '/^([a-zA-Z_]*)\.' . $encoding . '$/' ;
2020-05-06 16:06:05 +02:00
}
else {
2020-06-15 08:30:50 +02:00
if ( $with_encoding )
$regex = '/^([a-zA-Z_]+\.[a-zA-Z0-9\-]+)$/' ;
else
$regex = '/^([a-zA-Z_]+)\.[a-zA-Z0-9\-]+$/' ;
2020-05-06 16:06:05 +02:00
}
2021-06-29 16:46:50 +02:00
self :: log_trace ( " getLangList( " . varDump ( $encoding ) . " , $with_encoding ) : regex=' $regex ' " );
2021-06-29 16:50:25 +02:00
foreach ( array ( LS_I18N_DIR_PATH , LS_ROOT_DIR . '/' . LS_LOCAL_DIR . '/' . LS_I18N_DIR ) as $lang_dir ) {
2020-05-06 16:06:05 +02:00
if ( ! is_dir ( $lang_dir ))
continue ;
if ( $handle = opendir ( $lang_dir )) {
while ( false !== ( $file = readdir ( $handle ))) {
if ( is_dir ( " $lang_dir / $file " )) {
if ( preg_match ( $regex , $file , $regs )) {
if ( ! in_array ( $regs [ 1 ], $list )) {
$list [] = $regs [ 1 ];
}
}
}
}
}
}
return $list ;
}
/**
* Return current language
*
2022-12-31 05:52:31 +01:00
* @ param boolean $short If true , only return the two first characters of the language
2020-05-06 16:06:05 +02:00
* ( For instance , 'fr' for 'fr_FR' )
*
2022-12-31 05:52:31 +01:00
* @ return string The current language ( ex : fr_FR , or fr if $short == true )
2020-05-06 16:06:05 +02:00
**/
public static function getLang ( $short = false ) {
if ( $short ) {
return strtolower ( substr ( self :: $lang , 0 , 2 ));
}
return self :: $lang ;
}
/**
* Return current encoding
*
2022-12-31 05:52:31 +01:00
* @ return string The current encoding ( ex : UTF8 )
2020-05-06 16:06:05 +02:00
**/
public static function getEncoding () {
return self :: $encoding ;
}
/**
* Check a locale exists
*
2022-12-31 05:52:31 +01:00
* @ param string $lang The language ( ex : fr_FR )
2022-12-31 21:15:19 +01:00
* @ param string $encoding The encoding ( ex : UTF8 )
2020-05-06 16:06:05 +02:00
*
2022-12-31 05:52:31 +01:00
* @ return boolean True if the locale is available , False otherwise
2020-05-06 16:06:05 +02:00
**/
public static function localeExist ( $lang , $encoding ) {
if ( ! $lang && ! $encoding ) {
2023-01-02 01:17:46 +01:00
return false ;
2020-05-06 16:06:05 +02:00
}
$locale = $lang . (( $encoding ) ? '.' . $encoding : '' );
if ( $locale == 'en_US.UTF8' ) {
return true ;
}
2021-06-29 16:50:25 +02:00
foreach ( array ( LS_I18N_DIR_PATH , LS_ROOT_DIR . '/' . LS_LOCAL_DIR . '/' . LS_I18N_DIR ) as $lang_dir )
2020-05-06 16:06:05 +02:00
if ( is_dir ( " $lang_dir / $locale " ))
return true ;
return false ;
}
}
2020-05-06 17:48:49 +02:00
/*
***********************************************
* Generate translation file CLI methods
*
* Only load in CLI context
***********************************************
*/
2020-08-25 11:01:28 +02:00
if ( php_sapi_name () != " cli " ) return true ;
2020-05-06 17:48:49 +02:00
2022-12-31 02:01:17 +01:00
global $LSlang_cli_logger , $available_onlys , $available_withouts ;
2020-05-08 13:23:45 +02:00
2022-12-31 21:15:19 +01:00
/**
* Convert relative path to absolute
* @ param string $path The path to convert
* @ return string The converted absolute path
*/
2022-12-31 02:01:17 +01:00
function _cli_relative2absolute_path ( $path ) {
if ( $path [ 0 ] == '/' )
return $path ;
global $curdir ;
return realpath ( $curdir ) . " / " . $path ;
}
2022-12-31 21:15:19 +01:00
/**
* Convert absolute path to relative
* @ param string $path The path to convert
* @ return string The converted relative path
*/
2022-12-31 02:01:17 +01:00
function _cli_absolute2relative_path ( $path ) {
if ( $path [ 0 ] == '/' )
$path = realpath ( $path );
if ( substr ( $path , 0 , strlen ( LS_ROOT_DIR )) == LS_ROOT_DIR )
return substr ( $path , strlen ( LS_ROOT_DIR ) + 1 );
return $path ;
}
2022-12-31 21:15:19 +01:00
/**
* CLI Helper to ask user to translate a string
* @ param string $context The context of the string to translate
* @ param string $msg The string to convert
2023-01-02 01:17:46 +01:00
* @ return string | true The translated message string , true if $interactive_exit enabled
2022-12-31 21:15:19 +01:00
*/
2022-12-31 02:01:17 +01:00
function _cli_interactive_ask ( $context , $msg ) {
global $copyoriginalvalue , $interactive_exit ;
if ( $interactive_exit ) {
if ( $copyoriginalvalue )
return $msg ;
return true ;
}
// Format question
2023-03-21 11:33:42 +01:00
$question = " \" $msg\ " \n\n => " ._( " Please enter translated string " );
$empty_action = (
$copyoriginalvalue ?
_ ( " or leave empty to copy original message " ) :
_ ( " or leave empty to pass " )
);
2022-12-31 02:01:17 +01:00
$question .= " (i " ;
if ( ! $copyoriginalvalue )
$question .= " /c " ;
2023-03-21 11:33:42 +01:00
$question .= " /e/q/? $empty_action ): " ;
2022-12-31 02:01:17 +01:00
while ( true ) {
if ( $context )
fwrite ( STDERR , " \n # $context\n " );
fwrite ( STDERR , $question );
$in = trim ( fgets ( STDIN ));
switch ( $in ) {
case 'q' : // Exit interactive mode
case 'Q' :
$interactive_exit = true ;
return True ;
case 'i' : // Ignore
case 'I' :
return True ;
case 'c' :
case 'C' : // Copy
if ( ! $copyoriginalvalue )
return $msg ;
2023-03-21 11:33:42 +01:00
case 'e' :
case 'E' : // Open editor
$tmp_file = tempnam ( sys_get_temp_dir (), 'ldapsaisie_translation' );
if ( $tmp_file === false ) {
fwrite ( STDERR , _ ( 'Fail to create temporary file.' ));
break ;
}
$fd = fopen ( $tmp_file , 'w' );
if ( $fd === false ) {
fwrite ( STDERR , _ ( 'Fail to open temporary file.' ));
break ;
}
$nb_lines = 1 ;
if ( $context ) {
fwrite ( $fd , " # $context\n " );
$nb_lines ++ ;
}
$lines = explode ( " \n " , $msg );
$nb_lines += count ( $lines );
fwrite ( $fd , " # " . implode ( " \n # " , $lines ) . " \n \n " );
fclose ( $fd );
system ( " editor + $nb_lines $tmp_file > `tty` " , $exit_code );
$result = array ();
foreach ( file ( $tmp_file ) as $line )
if ( ! preg_match ( '/^# /' , $line ) || $result )
$result [] = preg_replace ( " / \n $ / " , " " , $line );
unlink ( $tmp_file );
return implode ( " \n " , $result );
2022-12-31 02:01:17 +01:00
case '?' : // Help message
2023-03-21 11:33:42 +01:00
fwrite ( STDERR , _ ( " Available choices: \n " ));
fwrite ( STDERR , _ ( " - i: ignore this message \n " ));
2022-12-31 02:01:17 +01:00
if ( ! $copyoriginalvalue )
2023-03-21 11:33:42 +01:00
fwrite ( STDERR , _ ( " - c: copy original message \n " ));
fwrite ( STDERR , _ ( " - e: translate message in text editor \n " ));
fwrite ( STDERR , _ ( " - q: quit interactive mode and ignore all following untranslated messages \n " ));
fwrite ( STDERR , _ ( " - ?: Show this message \n " ));
if ( $copyoriginalvalue )
fwrite ( STDERR , _ ( " Or leave empty to copy original message. \n " ));
else
fwrite ( STDERR , _ ( " Or leave empty to pass. \n " ));
2022-12-31 02:01:17 +01:00
break ;
case " " : // Empty
// On copy orignal value mode, return $msg
if ( $copyoriginalvalue )
return $msg ;
// Otherwise, leave translation empty
return " " ;
default :
// Return user input
return $in ;
}
}
// Supposed to never happen
return true ;
}
2022-12-31 21:15:19 +01:00
/**
* CLI helper to add string to translate
* @ param string $msg The string to translate
* @ param string | null $context The context of the string to translate
* @ return void
*/
2022-12-31 02:01:17 +01:00
function _cli_add_str_to_translate ( $msg , $context = null ) {
global $LSlang_cli_logger , $lang , $data , $translations , $interactive , $interactive_exit , $copyoriginalvalue , $format ;
$LSlang_cli_logger -> trace ( " _cli_add_str_to_translate( $msg , $context ) " );
if ( $msg == '' )
return ;
if ( ! is_null ( $lang ) && _ ( $msg ) != " $msg " )
return ;
// Message already exists ?
if ( array_key_exists ( $msg , $data )) {
if ( $context && ! in_array ( $context , $data [ $msg ][ 'contexts' ]))
$data [ $msg ][ 'contexts' ][] = $context ;
2022-12-31 21:15:19 +01:00
return ;
2022-12-31 02:01:17 +01:00
}
// Handle translation
$translation = " " ;
if ( array_key_exists ( $msg , $translations )) {
$translation = $translations [ $msg ];
}
elseif ( ! is_null ( $lang ) && _ ( $msg ) != $msg ) {
$translation = _ ( $msg );
}
elseif ( $interactive && $format != 'pot' ) {
$translation = _cli_interactive_ask ( $context , $msg );
if ( ! is_string ( $translation ))
2022-12-31 21:15:19 +01:00
return ;
2022-12-31 02:01:17 +01:00
}
$data [ $msg ] = array (
'translation' => $translation ,
'contexts' => ( $context ? array ( $context ) : array ()),
);
}
2022-12-31 21:15:19 +01:00
/**
* CLI helper to add string to translate from LSconfig
* @ param string $pattern The LSconfig parameter pattern used to find strings to translate
* @ param string $what Where to find string to translate . Possible values :
* - key : The LSconfig parameter key
* - value : The LSconfig parameter value
* @ param array $excludes Array of string to exclude
* @ return void
*/
function _cli_add_str_to_translate_from_LSconfig ( $pattern , $what = 'value' , $excludes = array ()) {
2022-12-31 02:01:17 +01:00
global $LSlang_cli_logger ;
$LSlang_cli_logger -> trace ( " _cli_add_str_to_translate_from_LSconfig( $pattern , array( " . implode ( ',' , $excludes ) . " )) " );
$keys = LSconfig :: getMatchingKeys ( $pattern );
$LSlang_cli_logger -> trace ( " addFromLSconfig : " . count ( $keys ) . " matching key(s) " );
foreach ( $keys as $key => $value ) {
$LSlang_cli_logger -> trace ( " addFromLSconfig : $key = " . varDump ( $value ));
2022-12-31 21:15:19 +01:00
if ( $what == 'key' ) {
2022-12-31 02:01:17 +01:00
// Get the last key parts as value and all other as key
$key_parts = explode ( '.' , $key );
$value = $key_parts [ count ( $key_parts ) - 1 ];
$key = implode ( '.' , array_slice ( $key_parts , 0 , count ( $key_parts ) - 1 ));
}
if ( ! in_array ( $value , $excludes ) && is_string ( $value ))
_cli_add_str_to_translate ( $value , $key );
}
}
2022-12-31 21:15:19 +01:00
/**
* CLI helper to add string to translate from list of possible values retreive from LSconfig
* @ param string $context The context == prefix of the LSconfig parameter key to retreive possible values
2023-01-02 01:17:46 +01:00
* @ param array < string > $withouts FIXME
2022-12-31 21:15:19 +01:00
* @ param integer $level The level of the possible value ( used to identify recursion level )
* @ return void
*/
2022-12-31 02:01:17 +01:00
function _cli_add_possible_values_from_LSconfig ( $context , $withouts , $level = 0 ) {
global $LSlang_cli_logger ;
$LSlang_cli_logger -> trace ( " _cli_add_possible_values_from_LSconfig( $context ) " );
if ( in_array ( 'select-list' , $withouts ))
2023-01-02 01:17:46 +01:00
return ;
2022-12-31 02:01:17 +01:00
if ( ! LSconfig :: get ( " $context .translate_labels " , True , " bool " ))
2023-01-02 01:17:46 +01:00
return ;
2022-12-31 02:01:17 +01:00
foreach ( LSconfig :: get ( " $context .possible_values " , array ()) as $pkey => $plabel ) {
if ( is_array ( $plabel )) {
// Sub possible values
// Check level
if ( $level > 1 ) {
$LSlang_cli_logger -> warning (
" _cli_add_possible_values_from_LSconfig( $context ): Level to hight to handle sub possible values of $context .possible_values. $pkey "
);
2023-01-02 01:17:46 +01:00
return ;
2022-12-31 02:01:17 +01:00
}
_cli_add_str_to_translate_from_LSconfig ( " $context .possible_values. $pkey .label " );
$LSlang_cli_logger -> trace ( " _cli_add_possible_values_from_LSconfig( $context ): handle sub possible values of $context .possible_values. $pkey " );
_cli_add_possible_values_from_LSconfig ( " $context .possible_values. $pkey " , $withouts , $level + 1 );
}
else {
switch ( $pkey ) {
case 'OTHER_OBJECT' :
$LSlang_cli_logger -> trace ( " _cli_add_possible_values_from_LSconfig( $context ): ignore $context .possible_values. $pkey (OTHER_OBJECT) " );
break ;
case 'OTHER_ATTRIBUTE' :
if ( is_array ( $plabel )) {
if ( isset ( $plabel [ 'json_component_key' ]))
_cli_add_str_to_translate_from_LSconfig ( " $context .possible_values.OTHER_ATTRIBUTE.json_component_label " );
else
_cli_add_str_to_translate_from_LSconfig ( " $context .possible_values.OTHER_ATTRIBUTE.* " );
}
else {
$LSlang_cli_logger -> warning ( " _cli_add_possible_values_from_LSconfig( $context ): invalid $context .possible_values.OTHER_ATTRIBUTE config => Must be an array. " );
}
break ;
default :
_cli_add_str_to_translate ( $plabel , " $context .possible_values. $pkey " );
break ;
}
}
}
}
2022-12-31 21:15:19 +01:00
/**
* CLI helper to parse a template file to locate strings to translate
* @ param string $file The file path
* @ return void
*/
2022-12-31 02:01:17 +01:00
function _cli_parse_template_file ( $file ) {
global $LSlang_cli_logger ;
$LSlang_cli_logger -> debug ( " Looking for string to translate in ' $file ' template file " );
$count = 0 ;
foreach ( file ( $file ) as $line ) {
$count ++ ;
if ( preg_match_all ( '/\{ *tr +msg=["\']([^\}]+)["\'] *\}/' , $line , $matches )) {
foreach ( $matches [ 1 ] as $t ) {
$t = preg_replace ( '/[\'"]\|escape\:.*$/' , '' , $t );
$LSlang_cli_logger -> trace ( " - \" $t\ " # Line $count");
_cli_add_str_to_translate ( $t , _cli_absolute2relative_path ( $file ) . " : $count " );
}
}
}
$LSlang_cli_logger -> trace ( " _cli_parse_template_file( $file ) : done. " );
}
2022-12-31 21:15:19 +01:00
/**
* CLI helper to find and parse all template files of the specified directory
* to locate strings to translate
* @ param string $dir The directory path
* @ return void
*/
2022-12-31 02:01:17 +01:00
function _cli_find_and_parse_template_file ( $dir ) {
if ( is_dir ( $dir )) {
if ( $dh = opendir ( $dir )) {
while (( $file = readdir ( $dh )) !== false ) {
if ( $file == '.' || $file == '..' ) continue ;
if ( is_dir ( $dir . '/' . $file )) {
_cli_find_and_parse_template_file ( $dir . '/' . $file );
}
elseif ( is_file ( $dir . " / " . $file ) && preg_match ( '/\.tpl$/' , $file )) {
_cli_parse_template_file ( $dir . '/' . $file );
}
}
closedir ( $dh );
}
}
}
2022-12-31 21:15:19 +01:00
/**
* CLI helper to parse a PHP file to locate strings to translate
* @ param string $file The file path
* @ return void
*/
2022-12-31 02:01:17 +01:00
function _cli_parse_php_file ( $file ) {
global $LSlang_cli_logger ;
$LSlang_cli_logger -> debug ( " Looking for string to translate in ' $file ' PHP file " );
$count = 0 ;
$quote = '' ;
$res = '' ;
foreach ( file ( $file ) as $line ) {
$count ++ ;
$LSlang_cli_logger -> trace ( " Handle line # $count of ' $file ' PHP file " );
$offset = 0 ;
while ( $pos = strpos ( $line , '__(' , $offset )) {
$LSlang_cli_logger -> trace ( " $file : $count : detect keyword at position # $pos (' $line ') " );
for ( $i = $pos + 3 ; $i < strlen ( $line ); $i ++ ) {
$offset = $i ; // Always increase offset to avoid infinity-loop
if ( empty ( $quote )) {
// Quote char not detected : try to detect it
if ( $line [ $i ] == '\\' || $line [ $i ] == " " || $line [ $i ] == " \t " ) {
// Space or escape char : pass
$i ++ ;
}
elseif ( $line [ $i ] == '"' || $line [ $i ] == " ' " ) {
// Quote detected
$quote = $line [ $i ];
}
elseif ( $line [ $i ] == '$' || $line [ $i ] == ')' ) {
// Variable translation not possible or end function call detected
break ;
}
else {
// Unknown case : continue
$i ++ ;
}
}
2022-12-31 04:09:56 +01:00
elseif ( $quote ) {
2022-12-31 02:01:17 +01:00
// Quote char already detected : try to detect end quote char
if ( $line [ $i ] == '\\' ) {
// Escape char detected : pass this char and the following one
$res .= $line [ $i ];
$i ++ ;
$res .= $line [ $i ];
}
elseif ( $line [ $i ] == $quote ) {
// End quote char detected : reset quote char detection and break detection
$quote = '' ;
break ;
}
else {
// End quote char not detected : append current char to result
$res .= $line [ $i ];
}
}
}
// Include detected string if not empty and quote char was detected and reseted
if ( ! empty ( $res ) && empty ( $quote )) {
_cli_add_str_to_translate ( $res , _cli_absolute2relative_path ( $file ) . " : $count " );
$res = '' ;
}
}
}
}
2022-12-31 21:15:19 +01:00
/**
* CLI helper to find and parse all PHP files of the specified directory
* to locate strings to translate
* @ param string $dir The directory path
* @ return void
*/
2022-12-31 02:01:17 +01:00
function _cli_find_and_parse_php_file ( $dir , $filename_regex ) {
if ( is_dir ( $dir )) {
if ( $dh = opendir ( $dir )) {
while (( $file = readdir ( $dh )) !== false ) {
if ( preg_match ( $filename_regex , $file )) {
_cli_parse_php_file ( $dir . '/' . $file );
}
}
closedir ( $dh );
}
}
}
2022-12-31 21:15:19 +01:00
/**
* CLI helper to generate output PHP translation file
* @ param resource $fd The file descriptor where to write to generated output
* @ return void
*/
2022-12-31 02:01:17 +01:00
function _cli_output_php ( $fd ) {
global $LSlang_cli_logger , $additionalfileformat , $data , $copyoriginalvalue , $keep_unused , $translations ;
fwrite ( $fd , " <?php \n \n " );
if ( ! $additionalfileformat ) fwrite ( $fd , " \$ GLOBALS['LSlang'] = array ( \n " );
foreach ( $data as $key => $key_data ) {
if ( $copyoriginalvalue && $key_data [ 'translation' ] == " " ) {
$val = $key ;
}
else
$val = $key_data [ 'translation' ];
$key = str_replace ( '"' , '\\"' , $key );
$val = str_replace ( '"' , '\\"' , $val );
foreach ( $key_data [ 'contexts' ] as $context )
fwrite ( $fd , " \n # $context " );
if ( $additionalfileformat ) {
fwrite ( $fd , " \n \$ GLOBALS['LSlang'][ \" $key\ " ] = \ " $val\ " ; \n " );
}
else {
fwrite ( $fd , " \n \" $key\ " => \n \ " $val\ " , \n " );
}
}
// Handle keep unused mode
if ( $keep_unused ) {
$unused_msgs = array ();
foreach ( $translations as $msg => $trans )
if ( ! array_key_exists ( $msg , $data ))
$unused_msgs [ $msg ] = $trans ;
if ( $unused_msgs ) {
fwrite ( $fd , " \n \n " );
fwrite ( $fd , " ###################################################################### \n " );
fwrite ( $fd , " # Unused translations keeped # \n " );
fwrite ( $fd , " ###################################################################### \n " );
foreach ( $unused_msgs as $key => $val ) {
$key = str_replace ( '"' , '\\"' , $key );
$val = str_replace ( '"' , '\\"' , $val );
if ( $additionalfileformat ) {
fwrite ( $fd , " \n \$ GLOBALS['LSlang'][ \" $key\ " ] = \ " $val\ " ; \n " );
}
else {
fwrite ( $fd , " \n \" $key\ " => \n \ " $val\ " , \n " );
}
}
}
}
if ( ! $additionalfileformat ) fwrite ( $fd , " \n ); \n " );
}
2022-12-31 21:15:19 +01:00
/**
* CLI helper to clean a orignal or translated message before writing it in a POT file
* @ param string $val The string to clean
* @ return string The cleaned string
*/
2022-12-31 02:01:17 +01:00
function _cli_clean_for_pot_file ( $val ) {
$val = str_replace ( '"' , '\\"' , $val );
return str_replace ( " \n " , " \\ n " , $val );
}
2022-12-31 21:15:19 +01:00
/**
* CLI helper to generate output POT translation file
* @ param resource $fd The file descriptor where to write to generated output
* @ return void
*/
2022-12-31 02:01:17 +01:00
function _cli_output_pot ( $fd ) {
global $LSlang_cli_logger , $data , $copyoriginalvalue ;
foreach ( $data as $key => $key_data ) {
if ( $copyoriginalvalue && $key_data [ 'translation' ] == " " ) {
$val = $key ;
}
else
$val = $key_data [ 'translation' ];
foreach ( $key_data [ 'contexts' ] as $context )
fwrite ( $fd , " #: $context\n " );
$key = _cli_clean_for_pot_file ( $key );
$val = _cli_clean_for_pot_file ( $val );
fwrite ( $fd , " msgid \" $key\ " \nmsgstr \ " $val\ " \n\n " );
}
}
$available_onlys = array ( " config " , " templates " , " addons " , " auth_methods " , " includes " );
$available_withouts = array_merge ( $available_onlys , array ( " select-list " ));
2022-12-31 21:15:19 +01:00
/**
* CLI generate_lang_file command
*
* @ param string $command_args Command arguments
*
* @ return boolean True on success , false otherwise
**/
2020-05-06 17:48:49 +02:00
function cli_generate_lang_file ( $command_args ) {
// Use global variables to share it with sub-functions
2020-05-08 13:23:45 +02:00
global $LSlang_cli_logger , $available_onlys , $available_withouts , $data , $translations , $interactive ,
2021-10-08 17:17:17 +02:00
$interactive_exit , $copyoriginalvalue , $format , $curdir , $additionalfileformat , $copyoriginalvalue ,
$keep_unused , $lang ;
2020-05-06 17:48:49 +02:00
2020-05-08 13:23:45 +02:00
// Initialize logger (if not already initialized by another CLI command)
if ( ! isset ( $LSlang_cli_logger ))
$LSlang_cli_logger = LSlog :: get_logger ( 'generate_lang_file' );
2020-05-06 17:48:49 +02:00
// Store existing translations
$translations = array ();
// Store output translations
$data = array ();
// Parameters
$only = null ;
$withouts = array ();
2021-01-29 15:23:22 +01:00
$include_upstream = false ;
2020-05-06 17:48:49 +02:00
$copyoriginalvalue = False ;
$interactive = False ;
2020-09-09 20:06:43 +02:00
$interactive_exit = False ; // Exit flag set when user type 'q'
2020-05-06 17:48:49 +02:00
$output = False ;
$additionalfileformat = False ;
2021-10-08 17:17:17 +02:00
$keep_unused = False ;
2021-10-08 17:20:31 +02:00
$fix_utf8 = False ;
2020-05-06 17:48:49 +02:00
$lang = null ;
$encoding = null ;
$available_formats = array ( 'php' , 'pot' );
$format = $available_formats [ 0 ];
$debug = false ;
$load_files = array ();
// Change directory
$curdir = getcwd ();
chdir ( dirname ( __FILE__ ) . '/../' );
for ( $i = 0 ; $i < count ( $command_args ); $i ++ ) {
switch ( $command_args [ $i ]) {
case '--without' :
case '-W' :
$i ++ ;
$without = strtolower ( $command_args [ $i ]);
if ( ! in_array ( $without , $available_withouts ))
2023-03-21 12:59:55 +01:00
LScli :: usage ( _ ( " Invalid -W/--without parameter. Must be one of the following values: %s.' " ), implode ( " ',' " , $available_withouts ));
2020-05-06 17:48:49 +02:00
elseif ( $only )
2023-03-21 12:59:55 +01:00
LScli :: usage ( _ ( " You could not use -W/--without parameter combined with -O/--only parameter. " ));
2020-05-06 17:48:49 +02:00
$withouts [] = $without ;
break ;
case '--only' :
case '-O' :
$i ++ ;
if ( $only )
2023-03-21 12:59:55 +01:00
LScli :: usage ( _ ( " You could specify only one -O/--only parameter. " ));
2020-05-06 17:48:49 +02:00
$only = strtolower ( $command_args [ $i ]);
if ( ! in_array ( $only , $available_onlys ))
2023-03-21 12:59:55 +01:00
LScli :: usage ( _ ( " Invalid -O/--only parameter. Must be one of the following values: %s.' " ), implode ( " ',' " , $available_onlys ));
2022-12-31 04:09:56 +01:00
elseif ( $withouts )
2023-03-21 12:59:55 +01:00
LScli :: usage ( _ ( " You could not use -W/--without parameter combined with -O/--only parameter. " ));
2020-05-06 17:48:49 +02:00
break ;
2021-01-29 15:23:22 +01:00
case '-I' :
case '--include-upstream' :
$include_upstream = True ;
break ;
2020-05-06 17:48:49 +02:00
case '--copy-original-value' :
case '-c' :
$copyoriginalvalue = True ;
break ;
case '--interactive' :
case '-i' :
$interactive = True ;
break ;
case '--additional-file-format' :
case '-a' :
$additionalfileformat = True ;
break ;
case '--lang' :
case '-l' :
$i ++ ;
$parse_lang = explode ( '.' , $command_args [ $i ]);
if ( count ( $parse_lang ) == 2 ) {
$lang = $parse_lang [ 0 ];
$encoding = $parse_lang [ 1 ];
}
else {
2023-03-21 12:59:55 +01:00
LScli :: usage ( _ ( " Invalid -l/--lang parameter. Must be compose in format : [lang].[encoding] " ));
2020-05-06 17:48:49 +02:00
}
break ;
case '--output' :
case '-o' :
$i ++ ;
$output = $command_args [ $i ];
break ;
case '--format' :
case '-f' :
$i ++ ;
$format = strtolower ( $command_args [ $i ]);
if ( ! in_array ( $format , $available_formats )) {
2023-03-21 12:59:55 +01:00
LScli :: usage ( _ ( " Invalid -f/--format parameter. Must be one of the following values: %s.' " ), implode ( " ',' " , $available_formats ));
2020-05-06 17:48:49 +02:00
}
break ;
case '--debug' :
case '-d' :
$debug = true ;
break ;
2021-10-08 17:17:17 +02:00
case '--keep-unused' :
case '-K' :
$keep_unused = true ;
break ;
2021-10-08 17:20:31 +02:00
case '--fix-utf8' :
case '-F' :
$fix_utf8 = true ;
break ;
2020-05-06 17:48:49 +02:00
default :
2022-12-31 02:01:17 +01:00
$path = _cli_relative2absolute_path ( $command_args [ $i ]);
2020-05-06 17:48:49 +02:00
if ( is_file ( $path ))
$load_files [] = $path ;
else
2023-03-21 12:59:55 +01:00
LScli :: usage ( _ ( " %s: Invalid parameter or lang file to load. " ), $command_args [ $i ]);
2020-05-06 17:48:49 +02:00
}
}
2021-10-08 17:20:31 +02:00
// In fix-utf8 mode, load ForceUT8/Encoding lib
if ( $fix_utf8 )
LSsession :: includeFile ( LS_LIB_DIR . " ForceUTF8/Encoding.php " );
2020-05-06 17:48:49 +02:00
// Load translation files
foreach ( $load_files as $path ) {
2020-05-08 13:23:45 +02:00
$LSlang_cli_logger -> debug ( " Load $path lang file " );
2020-05-06 17:48:49 +02:00
@ include ( $path );
foreach ( $GLOBALS [ 'LSlang' ] as $msg => $trans ) {
2021-10-08 17:20:31 +02:00
if ( $fix_utf8 )
$translations [ \ForceUTF8\Encoding :: fixUTF8 ( $msg )] = \ForceUTF8\Encoding :: fixUTF8 ( $trans );
else
$translations [ $msg ] = $trans ;
2020-05-06 17:48:49 +02:00
}
}
// Initialize session
LSlang :: setLocale ( $lang , $encoding );
// Load lang string if lang was specify
if ( $lang && $encoding && isset ( $GLOBALS [ 'LSlang' ]) && is_array ( $GLOBALS [ 'LSlang' ])) {
foreach ( $GLOBALS [ 'LSlang' ] as $msg => $trans ) {
2021-10-08 17:20:31 +02:00
if ( $fix_utf8 )
$translations [ \ForceUTF8\Encoding :: fixUTF8 ( $msg )] = \ForceUTF8\Encoding :: fixUTF8 ( $trans );
else
$translations [ $msg ] = $trans ;
2020-05-06 17:48:49 +02:00
}
}
/*
* Manage configuration parameters
*/
if ( ! in_array ( 'config' , $withouts ) && ( ! $only || $only == 'config' )) {
// LDAP Servers
$objects = array ();
2020-09-10 12:26:25 +02:00
$LSlang_cli_logger -> info ( " Looking for string to translate configuration of LDAP servers " );
2020-05-06 17:48:49 +02:00
foreach ( LSconfig :: keys ( 'ldap_servers' ) as $ldap_server_id ) {
2020-09-10 12:26:25 +02:00
$LSlang_cli_logger -> debug ( " Looking for string to translate configuration of LDAP server # $ldap_server_id " );
2022-12-31 02:01:17 +01:00
_cli_add_str_to_translate_from_LSconfig ( " ldap_servers. $ldap_server_id .name " );
_cli_add_str_to_translate_from_LSconfig ( " ldap_servers. $ldap_server_id .subDnLabel " );
_cli_add_str_to_translate_from_LSconfig ( " ldap_servers. $ldap_server_id .recoverPassword.recoveryHashMail.subject " );
_cli_add_str_to_translate_from_LSconfig ( " ldap_servers. $ldap_server_id .recoverPassword.recoveryHashMail.msg " );
_cli_add_str_to_translate_from_LSconfig ( " ldap_servers. $ldap_server_id .recoverPassword.newPasswordMail.subject " );
_cli_add_str_to_translate_from_LSconfig ( " ldap_servers. $ldap_server_id .recoverPassword.newPasswordMail.msg " );
_cli_add_str_to_translate_from_LSconfig ( " ldap_servers. $ldap_server_id .subDn.* " , 'key' , array ( " LSobject " ));
_cli_add_str_to_translate_from_LSconfig ( " ldap_servers. $ldap_server_id .LSprofiles.*.label " );
2020-05-06 17:48:49 +02:00
// LSaccess
foreach ( LSconfig :: get ( " ldap_servers. $ldap_server_id .LSaccess " , array ()) as $LSobject ) {
if ( is_string ( $LSobject ) && ! in_array ( $LSobject , $objects ) && LSsession :: loadLSobject ( $LSobject )) {
$objects [] = $LSobject ;
}
}
// Sub DN LSobjects
foreach ( LSconfig :: getMatchingKeys ( " ldap_servers. $ldap_server_id .subDn.*.LSobjects.* " ) as $LSobject )
if ( is_string ( $LSobject ) && ! in_array ( $LSobject , $objects ) && LSsession :: loadLSobject ( $LSobject ))
$objects [] = $LSobject ;
}
2020-05-08 13:23:45 +02:00
$LSlang_cli_logger -> debug ( 'LSobjects list : ' . implode ( ', ' , $objects ));
2020-05-06 17:48:49 +02:00
// LSobject
foreach ( $objects as $obj ) {
2020-09-10 12:26:25 +02:00
$LSlang_cli_logger -> info ( " Looking for string to translate configuration of object type $obj " );
2022-12-31 02:01:17 +01:00
_cli_add_str_to_translate_from_LSconfig ( " LSobjects. $obj .label " );
2020-05-06 17:48:49 +02:00
// LSrelation
2022-12-31 02:01:17 +01:00
_cli_add_str_to_translate_from_LSconfig ( " LSobjects. $obj .LSrelation.*.label " );
_cli_add_str_to_translate_from_LSconfig ( " LSobjects. $obj .LSrelation.*.emptyText " );
2020-05-06 17:48:49 +02:00
// Custom Actions
2022-12-31 02:01:17 +01:00
_cli_add_str_to_translate_from_LSconfig ( " LSobjects. $obj .customActions.*.label " );
_cli_add_str_to_translate_from_LSconfig ( " LSobjects. $obj .customActions.*.helpInfo " );
_cli_add_str_to_translate_from_LSconfig ( " LSobjects. $obj .customActions.*.question_format " );
_cli_add_str_to_translate_from_LSconfig ( " LSobjects. $obj .customActions.*.onSuccessMsgFormat " );
2020-05-06 17:48:49 +02:00
// LSform
2022-12-31 02:01:17 +01:00
_cli_add_str_to_translate_from_LSconfig ( " LSobjects. $obj .LSform.layout.*.label " );
_cli_add_str_to_translate_from_LSconfig ( " LSobjects. $obj .LSform.dataEntryForm.*.label " );
2020-05-06 17:48:49 +02:00
// LSsearch
2022-12-31 02:01:17 +01:00
_cli_add_str_to_translate_from_LSconfig ( " LSobjects. $obj .LSsearch.predefinedFilters.* " );
_cli_add_str_to_translate_from_LSconfig ( " LSobjects. $obj .LSsearch.extraDisplayedColumns.*.label " );
_cli_add_str_to_translate_from_LSconfig ( " LSobjects. $obj .LSsearch.extraDisplayedColumns.*.LSformat " );
_cli_add_str_to_translate_from_LSconfig ( " LSobjects. $obj .LSsearch.extraDisplayedColumns.*.alternativeLSformats.* " );
_cli_add_str_to_translate_from_LSconfig ( " LSobjects. $obj .LSsearch.extraDisplayedColumns.*.formaterLSformat " );
_cli_add_str_to_translate_from_LSconfig ( " LSobjects. $obj .LSsearch.customActions.*.label " );
_cli_add_str_to_translate_from_LSconfig ( " LSobjects. $obj .LSsearch.customActions.*.question_format " );
_cli_add_str_to_translate_from_LSconfig ( " LSobjects. $obj .LSsearch.customActions.*.onSuccessMsgFormat " );
2020-05-06 17:48:49 +02:00
// Attributes
foreach ( LSconfig :: keys ( " LSobjects. $obj .attrs " ) as $attr ) {
2022-12-31 02:01:17 +01:00
_cli_add_str_to_translate_from_LSconfig ( " LSobjects. $obj .attrs. $attr .label " );
_cli_add_str_to_translate_from_LSconfig ( " LSobjects. $obj .attrs. $attr .help_info " );
_cli_add_str_to_translate_from_LSconfig ( " LSobjects. $obj .attrs. $attr .no_value_label " );
_cli_add_str_to_translate_from_LSconfig ( " LSobjects. $obj .attrs. $attr .check_data.*.msg " );
_cli_add_str_to_translate_from_LSconfig ( " LSobjects. $obj .attrs. $attr .validation.*.msg " );
2020-05-06 17:48:49 +02:00
// HTML Options
$html_type = LSconfig :: get ( " LSobjects. $obj .attrs. $attr .html_type " );
switch ( $html_type ) {
case 'boolean' :
2022-12-31 02:01:17 +01:00
_cli_add_str_to_translate_from_LSconfig ( " LSobjects. $obj .attrs. $attr .html_options.true_label " );
_cli_add_str_to_translate_from_LSconfig ( " LSobjects. $obj .attrs. $attr .html_options.false_label " );
2020-05-06 17:48:49 +02:00
break ;
case 'jsonCompositeAttribute' :
$components = LSconfig :: keys ( " LSobjects. $obj .attrs. $attr .html_options.components " );
foreach ( $components as $c ) {
2022-12-31 02:01:17 +01:00
_cli_add_str_to_translate_from_LSconfig ( " LSobjects. $obj .attrs. $attr .html_options.components. $c .label " );
_cli_add_str_to_translate_from_LSconfig ( " LSobjects. $obj .attrs. $attr .html_options.components. $c .help_info " );
_cli_add_str_to_translate_from_LSconfig ( " LSobjects. $obj .attrs. $attr .html_options.components. $c .check_data.*.msg " );
2020-05-06 17:48:49 +02:00
2020-09-10 12:09:26 +02:00
if ( LSconfig :: get ( " LSobjects. $obj .attrs. $attr .html_options.components. $c .type " ) == 'select_list' )
2022-12-31 02:01:17 +01:00
_cli_add_possible_values_from_LSconfig ( " LSobjects. $obj .attrs. $attr .html_options.components. $c .options " , $withouts );
2020-05-06 17:48:49 +02:00
}
break ;
case 'labeledValue' :
2020-11-25 15:46:25 +01:00
if ( LSconfig :: get ( " LSobjects. $obj .attrs. $attr .html_options.translate_labels " , True , " bool " ))
2022-12-31 02:01:17 +01:00
_cli_add_str_to_translate_from_LSconfig ( " LSobjects. $obj .attrs. $attr .html_options.labels.* " );
2020-05-06 17:48:49 +02:00
break ;
case 'password' :
2022-12-31 02:01:17 +01:00
_cli_add_str_to_translate_from_LSconfig ( " LSobjects. $obj .attrs. $attr .html_options.mail.subject " );
_cli_add_str_to_translate_from_LSconfig ( " LSobjects. $obj .attrs. $attr .html_options.mail.msg " );
_cli_add_str_to_translate_from_LSconfig ( " LSobjects. $obj .attrs. $attr .html_options.confirmChangeQuestion " );
2020-05-06 17:48:49 +02:00
break ;
case 'select_list' :
case 'select_box' :
2022-12-31 02:01:17 +01:00
_cli_add_possible_values_from_LSconfig ( " LSobjects. $obj .attrs. $attr .html_options " , $withouts );
2020-05-06 17:48:49 +02:00
break ;
case 'valueWithUnit' :
2022-12-31 02:01:17 +01:00
_cli_add_str_to_translate_from_LSconfig ( " LSobjects. $obj .attrs. $attr .html_options.units.* " );
2020-05-06 17:48:49 +02:00
break ;
2020-09-09 18:40:44 +02:00
case 'date' :
2022-12-31 02:01:17 +01:00
_cli_add_str_to_translate_from_LSconfig ( " LSobjects. $obj .attrs. $attr .html_options.special_values.* " );
2020-09-09 18:40:44 +02:00
break ;
2020-05-06 17:48:49 +02:00
}
}
}
}
/*
* Manage template file
*/
if ( ! in_array ( 'templates' , $withouts ) && ( ! $only || $only == 'templates' )) {
2020-09-10 12:26:25 +02:00
$LSlang_cli_logger -> info ( " Looking for string to translate in templates file " );
2022-12-31 02:01:17 +01:00
if ( $include_upstream ) _cli_find_and_parse_template_file ( LS_ROOT_DIR . '/' . LS_TEMPLATES_DIR );
_cli_find_and_parse_template_file ( LS_ROOT_DIR . '/' . LS_LOCAL_DIR . LS_TEMPLATES_DIR );
2020-05-06 17:48:49 +02:00
}
/*
2021-01-29 15:23:22 +01:00
* Manage custom PHP code / config files
2020-05-06 17:48:49 +02:00
*/
2022-12-31 02:01:17 +01:00
// Manage includes files
2021-01-29 15:23:22 +01:00
if ( ! in_array ( 'includes' , $withouts ) && ( ! $only || $only == 'includes' )) {
// Note: Upstream code most only use gettext translation, do not handle it here
2022-12-31 02:01:17 +01:00
if ( $include_upstream ) _cli_find_and_parse_php_file ( LS_ROOT_DIR . '/' . LS_INCLUDE_DIR , '/^(.+)\.php$/' );
_cli_find_and_parse_php_file ( LS_ROOT_DIR . '/' . LS_LOCAL_DIR . LS_INCLUDE_DIR , '/^(.+)\.php$/' );
if ( $include_upstream ) _cli_find_and_parse_php_file ( LS_ROOT_DIR . '/' . LS_CLASS_DIR , '/^class\.(.+)\.php$/' );
_cli_find_and_parse_php_file ( LS_ROOT_DIR . '/' . LS_LOCAL_DIR . LS_CLASS_DIR , '/^class\.(.+)\.php$/' );
2021-01-29 15:23:22 +01:00
}
2022-12-31 02:01:17 +01:00
// Manage addons files
2021-01-29 15:23:22 +01:00
if ( ! in_array ( 'addons' , $withouts ) && ( ! $only || $only == 'addons' )) {
2020-09-10 12:26:25 +02:00
$LSlang_cli_logger -> info ( " Looking for string to translate in LSaddons PHP code " );
2022-12-31 02:01:17 +01:00
if ( $include_upstream ) _cli_find_and_parse_php_file ( LS_ROOT_DIR . '/' . LS_ADDONS_DIR , '/^LSaddons\.(.+)\.php$/' );
_cli_find_and_parse_php_file ( LS_ROOT_DIR . '/' . LS_LOCAL_DIR . LS_ADDONS_DIR , '/^LSaddons\.(.+)\.php$/' );
2021-01-29 15:23:22 +01:00
$LSlang_cli_logger -> info ( " Looking for string to translate in LSaddons configuration files " );
2022-12-31 02:01:17 +01:00
if ( $include_upstream ) _cli_find_and_parse_php_file ( LS_ROOT_DIR . '/' . LS_CONF_DIR . '/LSaddons' , '/^config\.LSaddons\.(.+)\.php$$/' );
_cli_find_and_parse_php_file ( LS_ROOT_DIR . '/' . LS_LOCAL_DIR . LS_CONF_DIR . '/LSaddons' , '/^config\.LSaddons\.(.+)\.php$$/' );
2021-01-29 15:23:22 +01:00
}
2022-12-31 02:01:17 +01:00
// Manage auth methods files
2021-01-29 15:23:22 +01:00
if ( ! in_array ( 'auth_methods' , $withouts ) && ( ! $only || $only == 'auth_methods' )) {
$LSlang_cli_logger -> info ( " Looking for string to translate in LSauthMethods configuration files " );
2022-12-31 02:01:17 +01:00
if ( $include_upstream ) _cli_find_and_parse_php_file ( LS_ROOT_DIR . '/' . LS_CONF_DIR . '/LSauth' , '/^config\.(.+)\.php$$/' );
_cli_find_and_parse_php_file ( LS_ROOT_DIR . '/' . LS_LOCAL_DIR . LS_CONF_DIR . '/LSauth' , '/^config\.(.+)\.php$$/' );
2020-05-06 17:48:49 +02:00
}
// Sort resulting strings
ksort ( $data );
/*
* Handle output file format
*/
// Determine where to write result
if ( $output ) {
2022-12-31 02:01:17 +01:00
$output = _cli_relative2absolute_path ( $output );
2020-09-10 12:26:25 +02:00
$LSlang_cli_logger -> info ( " Write result in output file ( $output ) " );
2022-12-31 04:09:56 +01:00
$fd = null ;
2020-05-06 17:48:49 +02:00
try {
2020-05-08 13:23:45 +02:00
$LSlang_cli_logger -> debug ( " Open output file ( $output ) " );
2020-05-06 17:48:49 +02:00
$fd = fopen ( $output , 'w' );
}
catch ( Exception $e ) {
2020-05-08 13:23:45 +02:00
$LSlang_cli_logger -> error ( 'Error occured opening output file : ' . $e -> getMessage (), " \n " );
2020-05-06 17:48:49 +02:00
}
if ( ! $fd ) {
2020-05-08 13:23:45 +02:00
$LSlang_cli_logger -> error ( " Use stdout out instead. \n " );
2020-05-06 17:48:49 +02:00
$fd = STDOUT ;
$output = false ;
}
}
else
$fd = STDOUT ;
// Generate output
2020-05-08 13:23:45 +02:00
$LSlang_cli_logger -> debug ( " Output format : $format " );
2020-05-06 17:48:49 +02:00
switch ( $format ) {
case 'pot' :
2022-12-31 02:01:17 +01:00
_cli_output_pot ( $fd );
2020-05-06 17:48:49 +02:00
break ;
case 'php' :
default :
2022-12-31 02:01:17 +01:00
_cli_output_php ( $fd );
2020-05-06 17:48:49 +02:00
break ;
}
// Close output file (is specified)
if ( $output && $fd != STDOUT ) {
2020-05-08 13:23:45 +02:00
$LSlang_cli_logger -> debug ( " Close output file ( $output ) " );
2020-05-06 17:48:49 +02:00
fclose ( $fd );
}
2020-05-06 19:57:14 +02:00
return true ;
2020-05-06 17:48:49 +02:00
}
2020-06-15 08:30:50 +02:00
/**
* Args autocompleter for CLI command generate_lang_file
*
2022-12-31 21:15:19 +01:00
* @ param array $comp_words List of already typed words of the command
* @ param int $comp_word_num The command word number to autocomplete
* @ param string $comp_word The command word to autocomplete
2023-01-02 01:17:46 +01:00
* @ param array < string > $opts List of global available options
2020-06-15 08:30:50 +02:00
*
2023-01-02 01:17:46 +01:00
* @ return array < string > List of available options for the word to autocomplete
2020-06-30 09:58:22 +02:00
**/
2020-06-15 08:30:50 +02:00
function cli_generate_lang_file_args_autocompleter ( $comp_words , $comp_word_num , $comp_word , $opts ) {
global $available_withouts , $available_onlys ;
switch ( $comp_words [ $comp_word_num - 1 ]) {
case '-W' :
case '--without' :
return LScli :: autocomplete_opts ( $available_withouts , $comp_word );
break ;
case '-O' :
case '--only' :
return LScli :: autocomplete_opts ( $available_onlys , $comp_word );
break ;
case '-l' :
case '--lang' :
return LScli :: autocomplete_opts ( LSlang :: getLangList ( false , true ), $comp_word );
break ;
case '-o' :
case '--output' :
return array ();
break ;
case '-f' :
case '--format' :
return LScli :: autocomplete_opts ( array ( 'php' , 'pot' ), $comp_word );
break ;
}
$opts = array_merge (
$opts ,
array (
'-W' , '--without' ,
'-O' , '--only' ,
'-c' , '--copy-original-value' ,
'-i' , '--interactive' ,
'-a' , '--additional-file-format' ,
'-l' , '--lang' ,
'-o' , '--output' ,
'-f' , '--format' ,
2021-01-29 15:23:22 +01:00
'-I' , '--include-upstream' ,
2021-10-08 17:17:17 +02:00
'-K' , '--keep-unused' ,
2021-10-08 17:20:31 +02:00
'-F' , '--fix-utf8' ,
2020-06-15 08:30:50 +02:00
)
);
return LScli :: autocomplete_opts ( $opts , $comp_word );
}
2020-05-06 17:48:49 +02:00
LScli :: add_command (
'generate_lang_file' ,
'cli_generate_lang_file' ,
2023-03-21 12:59:55 +01:00
___ ( 'Generate lang.php file' ),
'-l [lang] [-o output.file] [file1] [file2] [-h] [options]' ,
2020-05-06 17:48:49 +02:00
array (
2023-03-21 12:59:55 +01:00
___ (
" -W/--without Disable specified messages. Must be one of
the following values : " ),
2020-05-06 17:48:49 +02:00
" - " . implode ( " \n - " , $available_withouts ),
2023-03-21 12:59:55 +01:00
___ (
" -O/--only Only handle specified messages. Must be one
of the following values : " ),
2020-05-06 17:48:49 +02:00
" - " . implode ( " \n - " , $available_onlys ),
2023-03-21 12:59:55 +01:00
___ (
" -I/--include-upstream Include upstream code to message lookup
- c /-- copy - original - value Copy original value as translated value when
no translated value exists
- i /-- interactive Interactive mode : ask user to enter
translated on each translation needed
- a /-- additional - file - format Additional file format output
- l /-- lang Language of the translation
Format : [ lang ] . [ encoding ]
- o /-- output Output file ( default : stdout )
- f /-- format Output file format : php or pot
( default : php )
- K /-- keep - unused Keep unused translations in resulting file
- F /-- fix - utf8 Try to load and fix broken UTF - 8 characters
in existing lang files . " )
2020-05-06 18:37:02 +02:00
),
2020-06-15 08:30:50 +02:00
false , // This command does not need LDAP connection
'cli_generate_lang_file_args_autocompleter'
2020-05-06 17:48:49 +02:00
);
2020-05-06 19:58:57 +02:00
/**
* CLI generate_ldapsaisie_pot command
*
2022-12-31 21:15:19 +01:00
* @ param string $command_args Command arguments
2020-05-06 19:58:57 +02:00
*
2022-12-31 05:52:31 +01:00
* @ return boolean True on success , false otherwise
2020-05-06 19:58:57 +02:00
**/
function cli_generate_ldapsaisie_pot ( $command_args ) {
2020-05-08 13:23:45 +02:00
global $LSlang_cli_logger ;
// Initialize logger (if not already initialized by another CLI command)
if ( ! isset ( $LSlang_cli_logger ))
$LSlang_cli_logger = LSlog :: get_logger ( 'generate_ldapsaisie_pot' );
2020-05-12 19:24:38 +02:00
2020-05-06 19:58:57 +02:00
// Clean php file in tmp directory
if ( is_dir ( LS_TMP_DIR_PATH )) {
foreach ( listFiles ( LS_TMP_DIR_PATH , '/\.php$/' ) as $file ) {
$tmp_file = LS_TMP_DIR_PATH . $file ;
2020-05-08 13:23:45 +02:00
$LSlang_cli_logger -> debug ( " Remove temporary file ' $tmp_file ' " );
2020-05-06 19:58:57 +02:00
if ( ! unlink ( $tmp_file )) {
2020-05-08 13:23:45 +02:00
$LSlang_cli_logger -> fatal ( " Fail to delete temporary file ' $tmp_file '. " );
2020-05-06 19:58:57 +02:00
}
}
}
// List PHP files to parse
$php_files = LScli :: run_external_command (
2022-06-14 17:05:53 +02:00
array ( 'find' , '-name' , " '*.php' " ),
2020-05-06 19:58:57 +02:00
null , // no STDIN data
2022-06-14 17:05:53 +02:00
false , // do not escape command args (already done)
LS_ROOT_DIR // run in LdapSaisie root directory to retreive relative paths
2020-05-06 19:58:57 +02:00
);
if ( ! is_array ( $php_files ) || $php_files [ 0 ] != 0 ) {
2020-05-08 13:23:45 +02:00
$LSlang_cli_logger -> fatal ( " Fail to list PHP files. " );
2023-01-02 01:17:46 +01:00
return false ;
2020-05-06 19:58:57 +02:00
}
// Extract messages from LdapSaisie PHP files using xgettext
$result = LScli :: run_external_command (
array (
" xgettext " ,
" --from-code utf-8 " ,
" --language=PHP " ,
" -o " , LS_I18N_DIR_PATH . " /ldapsaisie-main.pot " , // Output
" --omit-header " , // No POT header
" --keyword=__ " , // Handle custom __() translation function
2020-06-30 09:58:22 +02:00
" --keyword=___ " , // Handle custom ___() translation function
2020-05-06 19:58:57 +02:00
" --files=- " // Read files to parse from STDIN
),
2022-06-14 17:05:53 +02:00
$php_files [ 1 ], // Pass PHP files list via STDIN
true , // Escape parameters
LS_ROOT_DIR // Run in LdapSaisie root directory
2020-05-06 19:58:57 +02:00
);
if ( ! is_array ( $result ) || $result [ 0 ] != 0 )
2020-05-08 13:23:45 +02:00
$LSlang_cli_logger -> fatal ( " Fail to extract messages from PHP files using xgettext. " );
2020-05-06 19:58:57 +02:00
// Extract other messages from LdapSaisie templates files
$result = LScli :: run_command (
'generate_lang_file' ,
array (
" -o " , LS_I18N_DIR_PATH . " /ldapsaisie-templates.pot " ,
" -f " , " pot " ,
" --only " , " templates " ,
2021-01-29 15:23:22 +01:00
" --include-upstream " ,
2020-05-06 19:58:57 +02:00
),
false // do not exit
);
if ( ! $result )
2020-05-08 13:23:45 +02:00
$LSlang_cli_logger -> fatal ( " Fail to extract messages from template files using generate_lang_file command. " );
2020-05-06 19:58:57 +02:00
// Merge previous results in ldapsaisie.pot file using msgcat
$result = LScli :: run_external_command ( array (
'msgcat' ,
LS_I18N_DIR_PATH . " /ldapsaisie-main.pot " ,
LS_I18N_DIR_PATH . " /ldapsaisie-templates.pot " ,
" -o " , LS_I18N_DIR_PATH . " /ldapsaisie.pot " ,
));
if ( ! is_array ( $result ) || $result [ 0 ] != 0 )
2020-05-08 13:23:45 +02:00
$LSlang_cli_logger -> fatal ( " Fail to merge messages using msgcat. " );
2020-05-06 19:58:57 +02:00
return true ;
}
LScli :: add_command (
'generate_ldapsaisie_pot' ,
'cli_generate_ldapsaisie_pot' ,
2023-03-21 12:59:55 +01:00
___ ( 'Generate POT files:' ),
2020-05-06 19:58:57 +02:00
null ,
array (
2023-03-21 12:59:55 +01:00
___ ( " This command generate 3 POT files: " ),
2020-05-06 19:58:57 +02:00
" - " . LS_I18N_DIR_PATH . " /ldapsaisie-main.pot " ,
2023-03-21 12:59:55 +01:00
___ ( " => contains messages from PHP files " ),
2020-05-06 19:58:57 +02:00
" - " . LS_I18N_DIR_PATH . " /ldapsaisie-templates.pot " ,
2023-03-21 12:59:55 +01:00
___ ( " => contains messages from templates files " ),
2020-05-06 19:58:57 +02:00
" - " . LS_I18N_DIR_PATH . " /ldapsaisie.pot " ,
2023-03-21 12:59:55 +01:00
___ ( " => contains all messages " ),
2020-05-06 19:58:57 +02:00
),
false // This command does not need LDAP connection
);