2003-05-02 12:33:06 +02:00
< ? php
2010-04-19 11:34:50 +02:00
/* Copyright ( C ) 2001 Eric Seigne < erics @ rycks . com >
2015-10-13 13:27:44 +02:00
* Copyright ( C ) 2004 - 2015 Destailleur Laurent < eldy @ users . sourceforge . net >
2012-12-30 15:11:07 +01:00
* Copyright ( C ) 2005 - 2010 Regis Houssin < regis . houssin @ capnetworks . com >
2003-05-02 12:33:06 +02:00
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
2013-01-16 15:36:08 +01:00
* the Free Software Foundation ; either version 3 of the License , or
2003-05-02 12:33:06 +02:00
* any later version .
*
* 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
2011-08-01 01:45:11 +02:00
* along with this program . If not , see < http :// www . gnu . org / licenses />.
2010-04-19 11:34:50 +02:00
*/
2003-05-02 12:33:06 +02:00
2005-01-02 17:57:37 +01:00
/**
2010-06-08 01:52:43 +02:00
* \file htdocs / core / class / translate . class . php
2010-11-22 10:18:53 +01:00
* \ingroup core
2008-10-09 19:29:32 +02:00
* \brief File for Tanslate class
2008-08-07 08:33:35 +02:00
*/
2004-08-15 20:09:30 +02:00
2008-01-21 03:19:25 +01:00
/**
2012-01-27 16:10:44 +01:00
* Class to manage translations
2008-08-07 08:33:35 +02:00
*/
2012-01-14 14:27:27 +01:00
class Translate
{
2017-01-21 16:12:25 +01:00
public $dir ; // Directories that contains /langs subdirectory
2008-03-31 17:17:39 +02:00
2017-01-21 16:12:25 +01:00
public $defaultlang ; // Current language for current user
public $charset_output = 'UTF-8' ; // Codage used by "trans" method outputs
2005-02-06 19:41:45 +01:00
2017-01-21 16:12:25 +01:00
public $tab_translate = array (); // Array of all translations key=>value
private $_tab_loaded = array (); // Array to store result after loading each language file
2009-01-15 23:49:06 +01:00
2017-01-21 16:12:25 +01:00
public $cache_labels = array (); // Cache for labels return by getLabelFromKey method
public $cache_currencies = array (); // Cache to store currency symbols
2017-04-14 18:08:02 +02:00
private $cache_currencies_all_loaded = false ;
2009-01-15 23:49:06 +01:00
2003-05-02 12:33:06 +02:00
2009-05-11 18:26:54 +02:00
/**
2011-09-11 20:35:38 +02:00
* Constructor
2011-08-16 01:17:14 +02:00
*
2017-12-13 23:37:34 +01:00
* @ param string $dir Force directory that contains / langs subdirectory ( value is sometimes '..' like into install /* pages or support /* pages ) . Use '' by default .
2011-12-07 17:28:11 +01:00
* @ param Conf $conf Object with Dolibarr configuration
2009-05-11 18:26:54 +02:00
*/
2017-12-13 23:37:34 +01:00
function __construct ( $dir , $conf )
2009-05-11 18:26:54 +02:00
{
2011-01-30 14:35:00 +01:00
if ( ! empty ( $conf -> file -> character_set_client )) $this -> charset_output = $conf -> file -> character_set_client ; // If charset output is forced
2008-12-07 20:19:32 +01:00
if ( $dir ) $this -> dir = array ( $dir );
2009-05-08 03:23:33 +02:00
else $this -> dir = $conf -> file -> dol_document_root ;
2009-05-11 18:26:54 +02:00
}
2005-10-30 02:07:00 +01:00
2009-05-11 18:26:54 +02:00
/**
2011-01-30 14:35:00 +01:00
* Set accessor for this -> defaultlang
2011-08-16 01:17:14 +02:00
*
2013-02-24 02:42:37 +01:00
* @ param string $srclang Language to use . If '' or 'auto' , we use browser lang .
2012-01-14 14:27:27 +01:00
* @ return void
2009-05-11 18:26:54 +02:00
*/
2012-02-20 01:31:02 +01:00
function setDefaultLang ( $srclang = 'en_US' )
2009-05-11 18:26:54 +02:00
{
2011-01-30 14:35:00 +01:00
global $conf ;
2011-03-08 16:14:42 +01:00
2012-01-14 14:27:27 +01:00
//dol_syslog(get_class($this)."::setDefaultLang srclang=".$srclang,LOG_DEBUG);
2009-05-11 18:26:54 +02:00
2011-01-30 14:35:00 +01:00
// If a module ask to force a priority on langs directories (to use its own lang files)
2011-03-08 16:14:42 +01:00
if ( ! empty ( $conf -> global -> MAIN_FORCELANGDIR ))
2011-01-30 14:35:00 +01:00
{
$more = array ();
2011-08-16 01:17:14 +02:00
$i = 0 ;
2011-01-30 14:35:00 +01:00
foreach ( $conf -> file -> dol_document_root as $dir )
{
2012-01-14 14:27:27 +01:00
$newdir = $dir . $conf -> global -> MAIN_FORCELANGDIR ; // For example $conf->global->MAIN_FORCELANGDIR is '/mymodule' meaning we search files into '/mymodule/langs/xx_XX'
2011-08-16 01:17:14 +02:00
if ( ! in_array ( $newdir , $this -> dir ))
{
2012-01-14 14:27:27 +01:00
$more [ 'module_' . $i ] = $newdir ; $i ++ ; // We add the forced dir into the array $more. Just after, we add entries into $more to list of lang dir $this->dir.
2011-08-16 01:17:14 +02:00
}
2011-01-30 14:35:00 +01:00
}
2012-01-14 14:27:27 +01:00
$this -> dir = array_merge ( $more , $this -> dir ); // Forced dir ($more) are before standard dirs ($this->dir)
2011-01-30 14:35:00 +01:00
}
2011-03-08 16:14:42 +01:00
2009-05-11 18:26:54 +02:00
$this -> origlang = $srclang ;
if ( empty ( $srclang ) || $srclang == 'auto' )
{
2012-04-04 20:18:39 +02:00
$langpref = empty ( $_SERVER [ 'HTTP_ACCEPT_LANGUAGE' ]) ? '' : $_SERVER [ 'HTTP_ACCEPT_LANGUAGE' ];
2009-10-21 16:02:14 +02:00
$langpref = preg_replace ( " /;([^,]*)/i " , " " , $langpref );
$langpref = str_replace ( " - " , " _ " , $langpref );
2009-10-20 15:14:44 +02:00
$langlist = preg_split ( " /[;,]/ " , $langpref );
2009-08-12 19:40:47 +02:00
$codetouse = $langlist [ 0 ];
}
else $codetouse = $srclang ;
2011-03-30 17:53:51 +02:00
2009-08-12 19:40:47 +02:00
// We redefine $srclang
2009-10-20 15:14:44 +02:00
$langpart = explode ( " _ " , $codetouse );
2017-11-19 21:22:14 +01:00
//print "Short code before _ : ".$langpart[0].' / Short code after _ : '.$langpart[1].'<br>';
2012-02-20 01:31:02 +01:00
if ( ! empty ( $langpart [ 1 ])) // If it's for a codetouse that is a long code xx_YY
2009-08-12 19:40:47 +02:00
{
2011-03-31 17:11:53 +02:00
// Array force long code from first part, even if long code is defined
$longforshort = array ( 'ar' => 'ar_SA' );
2017-11-19 21:22:14 +01:00
$longforshortexcep = array ( 'ar_EG' );
if ( isset ( $longforshort [ strtolower ( $langpart [ 0 ])]) && ! in_array ( $codetouse , $longforshortexcep )) $srclang = $longforshort [ strtolower ( $langpart [ 0 ])];
2013-10-11 10:01:47 +02:00
else if ( ! is_numeric ( $langpart [ 1 ])) { // Second part YY may be a numeric with some Chrome browser
2009-05-11 18:26:54 +02:00
$srclang = strtolower ( $langpart [ 0 ]) . " _ " . strtoupper ( $langpart [ 1 ]);
$longforlong = array ( 'no_nb' => 'nb_NO' );
if ( isset ( $longforlong [ strtolower ( $srclang )])) $srclang = $longforlong [ strtolower ( $srclang )];
}
2013-10-11 10:01:47 +02:00
else $srclang = strtolower ( $langpart [ 0 ]) . " _ " . strtoupper ( $langpart [ 0 ]);
2009-08-12 19:40:47 +02:00
}
2011-03-30 17:52:27 +02:00
else { // If it's for a codetouse that is a short code xx
2011-03-31 17:11:53 +02:00
// Array to convert short lang code into long code.
$longforshort = array ( 'ar' => 'ar_SA' , 'el' => 'el_GR' , 'ca' => 'ca_ES' , 'en' => 'en_US' , 'nb' => 'nb_NO' , 'no' => 'nb_NO' );
2009-08-12 19:40:47 +02:00
if ( isset ( $longforshort [ strtolower ( $langpart [ 0 ])])) $srclang = $longforshort [ strtolower ( $langpart [ 0 ])];
2012-02-20 01:31:02 +01:00
else if ( ! empty ( $langpart [ 0 ])) $srclang = strtolower ( $langpart [ 0 ]) . " _ " . strtoupper ( $langpart [ 0 ]);
else $srclang = 'en_US' ;
2009-05-11 18:26:54 +02:00
}
$this -> defaultlang = $srclang ;
2012-02-20 01:31:02 +01:00
//print 'this->defaultlang='.$this->defaultlang;
2009-05-11 18:26:54 +02:00
}
/**
2010-11-01 13:41:32 +01:00
* Return active language code for current user
* It ' s an accessor for this -> defaultlang
2011-08-16 01:17:14 +02:00
*
2018-02-13 20:13:35 +01:00
* @ param int $mode 0 = Long language code , 1 = Short language code ( en , fr , es , ... )
2011-12-07 17:28:11 +01:00
* @ return string Language code used ( en_US , en_AU , fr_FR , ... )
2009-05-11 18:26:54 +02:00
*/
2010-11-01 13:41:32 +01:00
function getDefaultLang ( $mode = 0 )
2009-05-11 18:26:54 +02:00
{
2010-11-01 13:41:32 +01:00
if ( empty ( $mode )) return $this -> defaultlang ;
else return substr ( $this -> defaultlang , 0 , 2 );
2009-05-11 18:26:54 +02:00
}
2017-03-03 13:27:51 +01:00
/**
* Load translation files .
*
* @ param array $domains Array of lang files to load
* @ return int < 0 if KO , 0 if already loaded or loading not required , > 0 if OK
*/
function loadLangs ( $domains )
{
foreach ( $domains as $domain )
{
$this -> load ( $domain );
}
}
2017-06-09 09:25:15 +02:00
2009-05-11 18:26:54 +02:00
/**
2010-11-22 10:18:53 +01:00
* Load translation key - value for a particular file , into a memory array .
* If data for file already loaded , do nothing .
* All data in translation array are stored in UTF - 8 format .
* tab_loaded is completed with $domain key .
2012-12-01 15:45:05 +01:00
* rule " we keep first entry found with we keep last entry found " so it is probably not what you want to do .
*
2011-05-25 15:27:07 +02:00
* Value for hash are : 1 : Loaded from disk , 2 : Not found , 3 : Loaded from cache
2011-08-16 01:17:14 +02:00
*
2011-11-01 18:36:06 +01:00
* @ param string $domain File name to load ( . lang file ) . Must be " file " or " file@module " for module language files :
* If $domain is " file@module " instead of " file " then we look for module lang file
* in htdocs / custom / modules / mymodule / langs / code_CODE / file . lang
* then in htdocs / module / langs / code_CODE / file . lang instead of htdocs / langs / code_CODE / file . lang
2015-03-06 03:10:01 +01:00
* @ param integer $alt 0 ( try xx_ZZ then 1 ), 1 ( try xx_XX then 2 ), 2 ( try en_US )
2011-11-01 18:36:06 +01:00
* @ param int $stopafterdirection Stop when the DIRECTION tag is found ( optimize speed )
* @ param int $forcelangdir To force a different lang directory
2016-09-04 14:45:43 +02:00
* @ param int $loadfromfileonly 1 = Do not load overwritten translation from file or old conf .
2012-11-04 21:19:12 +01:00
* @ return int < 0 if KO , 0 if already loaded or loading not required , > 0 if OK
2017-05-05 16:35:05 +02:00
* @ see loadLangs
2008-03-31 17:17:39 +02:00
*/
2016-09-04 14:45:43 +02:00
function load ( $domain , $alt = 0 , $stopafterdirection = 0 , $forcelangdir = '' , $loadfromfileonly = 0 )
2009-05-11 18:26:54 +02:00
{
2015-09-17 17:52:34 +02:00
global $conf , $db ;
2017-04-14 11:22:48 +02:00
//dol_syslog("Translate::Load Start domain=".$domain." alt=".$alt." forcelangdir=".$forcelangdir." this->defaultlang=".$this->defaultlang);
2017-06-09 09:25:15 +02:00
2008-02-19 22:04:23 +01:00
// Check parameters
if ( empty ( $domain ))
{
2017-04-14 11:22:48 +02:00
dol_print_error ( '' , get_class ( $this ) . " ::Load ErrorWrongParameters " );
return - 1 ;
2008-02-19 22:04:23 +01:00
}
2012-11-04 21:19:12 +01:00
if ( $this -> defaultlang == 'none_NONE' ) return 0 ; // Special language code to not translate keys
2017-06-09 09:25:15 +02:00
2017-04-14 11:22:48 +02:00
// Load $this->tab_translate[] from database
if ( empty ( $loadfromfileonly ) && count ( $this -> tab_translate ) == 0 ) $this -> loadFromDatabase ( $db ); // Nothing was loaded yet, so we load database.
2009-01-15 23:49:06 +01:00
2009-09-28 23:59:09 +02:00
2010-04-19 11:45:53 +02:00
$newdomain = $domain ;
2010-04-19 11:34:50 +02:00
$modulename = '' ;
2010-05-08 04:16:29 +02:00
2011-08-24 04:17:57 +02:00
// Search if a module directory name is provided into lang file name
if ( preg_match ( '/^([^@]+)@([^@]+)$/i' , $domain , $regs ))
2010-04-19 11:34:50 +02:00
{
2011-08-24 04:17:57 +02:00
$newdomain = $regs [ 1 ];
$modulename = $regs [ 2 ];
2010-04-19 11:34:50 +02:00
}
2009-09-28 04:53:19 +02:00
2011-05-09 21:42:56 +02:00
// Check cache
2012-01-11 01:06:34 +01:00
if ( ! empty ( $this -> _tab_loaded [ $newdomain ])) // File already loaded for this domain
2009-09-28 23:59:09 +02:00
{
2018-03-13 18:13:31 +01:00
//dol_syslog("Translate::Load already loaded for newdomain=".$newdomain);
2009-09-28 23:59:09 +02:00
return 0 ;
}
2011-05-09 21:42:56 +02:00
$fileread = 0 ;
2009-09-28 23:59:09 +02:00
$langofdir = ( empty ( $forcelangdir ) ? $this -> defaultlang : $forcelangdir );
// Redefine alt
2009-10-20 15:14:44 +02:00
$langarray = explode ( '_' , $langofdir );
2017-01-21 21:52:42 +01:00
if ( $alt < 1 && isset ( $langarray [ 1 ]) && ( strtolower ( $langarray [ 0 ]) == strtolower ( $langarray [ 1 ]) || in_array ( strtolower ( $langofdir ), array ( 'el_gr' )))) $alt = 1 ;
2014-08-08 10:50:37 +02:00
if ( $alt < 2 && strtolower ( $langofdir ) == 'en_us' ) $alt = 2 ;
2012-02-01 13:28:19 +01:00
2014-11-12 10:25:56 +01:00
if ( empty ( $langofdir )) // This may occurs when load is called without setting the language and without providing a value for forcelangdir
{
dol_syslog ( " Error: " . get_class ( $this ) . " ::Load was called but language was not set yet with langs->setDefaultLang(). Nothing will be loaded. " , LOG_WARNING );
return - 1 ;
}
2011-08-16 01:17:14 +02:00
foreach ( $this -> dir as $keydir => $searchdir )
2008-12-07 20:19:32 +01:00
{
2009-05-11 18:26:54 +02:00
// Directory of translation files
2011-08-24 04:17:57 +02:00
$file_lang = $searchdir . ( $modulename ? '/' . $modulename : '' ) . " /langs/ " . $langofdir . " / " . $newdomain . " .lang " ;
2009-12-16 19:57:51 +01:00
$file_lang_osencoded = dol_osencode ( $file_lang );
2012-12-01 15:45:05 +01:00
2009-12-16 19:57:51 +01:00
$filelangexists = is_file ( $file_lang_osencoded );
2009-01-02 23:02:52 +01:00
2018-03-14 11:51:13 +01:00
//dol_syslog(get_class($this).'::Load Try to read for alt='.$alt.' langofdir='.$langofdir.' newdomain='.$domain.' modulename='.$modulename.' file_lang='.$file_lang." => filelangexists=".$filelangexists);
2009-01-02 23:02:52 +01:00
2009-05-11 18:26:54 +02:00
if ( $filelangexists )
{
2012-12-01 15:45:05 +01:00
// TODO Move cache read out of loop on dirs or at least filelangexists
2011-08-24 04:17:57 +02:00
$found = false ;
2010-01-13 17:26:19 +01:00
2011-08-16 01:17:14 +02:00
// Enable caching of lang file in memory (not by default)
2010-05-08 04:16:29 +02:00
$usecachekey = '' ;
// Using a memcached server
2010-11-13 21:59:06 +01:00
if ( ! empty ( $conf -> memcached -> enabled ) && ! empty ( $conf -> global -> MEMCACHED_SERVER ))
2010-05-08 04:16:29 +02:00
{
2011-10-04 12:25:09 +02:00
$usecachekey = $newdomain . '_' . $langofdir . '_' . md5 ( $file_lang ); // Should not contains special chars
2010-05-08 04:16:29 +02:00
}
// Using cache with shmop. Speed gain: 40ms - Memory overusage: 200ko (Size of session cache file)
else if ( isset ( $conf -> global -> MAIN_OPTIMIZE_SPEED ) && ( $conf -> global -> MAIN_OPTIMIZE_SPEED & 0x02 ))
{
$usecachekey = $newdomain ;
}
2010-01-13 17:26:19 +01:00
2010-06-11 02:41:17 +02:00
if ( $usecachekey )
2008-01-20 17:05:50 +01:00
{
2011-08-16 01:17:14 +02:00
//dol_syslog('Translate::Load we will cache result into usecachekey '.$usecachekey);
2015-09-07 20:17:05 +02:00
//global $aaa; $aaa+=1;
//print $aaa." ".$usecachekey."\n";
2012-08-22 23:11:24 +02:00
require_once DOL_DOCUMENT_ROOT . '/core/lib/memory.lib.php' ;
2010-05-08 04:16:29 +02:00
$tmparray = dol_getcache ( $usecachekey );
2011-09-17 21:49:50 +02:00
if ( is_array ( $tmparray ) && count ( $tmparray ))
2008-12-07 20:19:32 +01:00
{
2016-07-06 13:26:49 +02:00
$this -> tab_translate += $tmparray ; // Faster than array_merge($tmparray,$this->tab_translate). Note: If a value already exists into tab_translate, value into tmparaay is not added.
2009-12-16 22:42:42 +01:00
//print $newdomain."\n";
//var_dump($this->tab_translate);
2010-06-11 02:55:15 +02:00
if ( $alt == 2 ) $fileread = 1 ;
2010-05-08 17:02:04 +02:00
$found = true ; // Found in dolibarr PHP cache
2008-12-07 20:19:32 +01:00
}
2008-01-20 17:05:50 +01:00
}
2009-12-16 19:57:51 +01:00
if ( ! $found )
2008-12-07 20:19:32 +01:00
{
2008-12-07 21:54:08 +01:00
if ( $fp = @ fopen ( $file_lang , " rt " ))
2009-05-11 18:26:54 +02:00
{
2010-05-08 04:16:29 +02:00
if ( $usecachekey ) $tabtranslatedomain = array (); // To save lang content in cache
2010-01-13 17:26:19 +01:00
2016-12-22 17:09:25 +01:00
/**
* Read each lines until a '=' ( with any combination of spaces around it )
* and split the rest until a line feed .
* This is more efficient than fgets + explode + trim by a factor of ~ 2.
*/
2017-06-09 09:25:15 +02:00
while ( $line = fscanf ( $fp , " %[^= ]%*[ =]%[^ \n ] " ))
2017-04-14 11:22:48 +02:00
{
2017-06-09 09:25:15 +02:00
if ( isset ( $line [ 1 ]))
2017-04-14 11:22:48 +02:00
{
2016-12-22 17:09:25 +01:00
list ( $key , $value ) = $line ;
2016-07-06 13:26:49 +02:00
//if ($domain == 'orders') print "Domain=$domain, found a string for $tab[0] with value $tab[1]. Currently in cache ".$this->tab_translate[$key]."<br>";
//if ($key == 'Order') print "Domain=$domain, found a string for key=$key=$tab[0] with value $tab[1]. Currently in cache ".$this->tab_translate[$key]."<br>";
2017-06-09 09:25:15 +02:00
if ( empty ( $this -> tab_translate [ $key ]))
2017-04-14 11:22:48 +02:00
{ // If translation was already found, we must not continue, even if MAIN_FORCELANGDIR is set (MAIN_FORCELANGDIR is to replace lang dir, not to overwrite entries)
2016-12-22 17:09:25 +01:00
$value = preg_replace ( '/\\n/' , " \n " , $value ); // Parse and render carriage returns
if ( $key == 'DIRECTION' ) { // This is to declare direction of language
if ( $alt < 2 || empty ( $this -> tab_translate [ $key ])) { // We load direction only for primary files or if not yet loaded
$this -> tab_translate [ $key ] = $value ;
if ( $stopafterdirection ) {
break ; // We do not save tab if we stop after DIRECTION
} elseif ( $usecachekey ) {
$tabtranslatedomain [ $key ] = $value ;
}
2009-08-11 14:28:30 +02:00
}
2017-05-09 10:08:04 +02:00
}
elseif ( $key [ 0 ] == '#' )
{
continue ;
}
else {
2016-12-22 17:09:25 +01:00
$this -> tab_translate [ $key ] = $value ;
2016-07-06 13:26:49 +02:00
//if ($domain == 'orders') print "$tab[0] value $value<br>";
2016-12-22 17:09:25 +01:00
if ( $usecachekey ) {
$tabtranslatedomain [ $key ] = $value ;
} // To save lang content in cache
2008-12-07 20:19:32 +01:00
}
2009-05-11 18:26:54 +02:00
}
}
}
2008-12-07 20:19:32 +01:00
fclose ( $fp );
2009-12-16 19:57:51 +01:00
$fileread = 1 ;
2010-01-13 17:26:19 +01:00
2011-08-24 04:17:57 +02:00
// TODO Move cache write out of loop on dirs
2010-06-11 02:41:17 +02:00
// To save lang content for usecachekey into cache
2011-09-17 21:49:50 +02:00
if ( $usecachekey && count ( $tabtranslatedomain ))
2009-12-16 19:57:51 +01:00
{
2011-08-17 23:39:08 +02:00
$ressetcache = dol_setcache ( $usecachekey , $tabtranslatedomain );
if ( $ressetcache < 0 )
{
$error = 'Failed to set cache for usecachekey=' . $usecachekey . ' result=' . $ressetcache ;
dol_syslog ( $error , LOG_ERR );
}
2009-12-16 19:57:51 +01:00
}
2011-08-16 01:17:14 +02:00
2015-09-17 15:35:51 +02:00
if ( empty ( $conf -> global -> MAIN_FORCELANGDIR )) break ; // Break loop on each root dir. If a module has forced dir, we do not stop loop.
2009-05-11 18:26:54 +02:00
}
2008-12-07 20:19:32 +01:00
}
2009-05-11 18:26:54 +02:00
}
2008-12-07 20:19:32 +01:00
}
2009-01-15 23:49:06 +01:00
2017-01-21 21:52:42 +01:00
// Now we complete with next file (fr_CA->fr_FR, es_MX->ex_ES, ...)
2009-09-28 23:59:09 +02:00
if ( $alt == 0 )
{
// This function MUST NOT contains call to syslog
//dol_syslog("Translate::Load loading alternate translation file (to complete ".$this->defaultlang."/".$newdomain.".lang file)", LOG_DEBUG);
$langofdir = strtolower ( $langarray [ 0 ]) . '_' . strtoupper ( $langarray [ 0 ]);
2017-11-19 21:22:14 +01:00
if ( $langofdir == 'el_EL' ) $langofdir = 'el_GR' ; // main parent for el_CY is not 'el_EL' but 'el_GR'
if ( $langofdir == 'ar_AR' ) $langofdir = 'ar_SA' ; // main parent for ar_EG is not 'ar_AR' but 'ar_SA'
2009-09-28 23:59:09 +02:00
$this -> load ( $domain , $alt + 1 , $stopafterdirection , $langofdir );
}
2017-01-21 21:52:42 +01:00
// Now we complete with reference file (en_US)
2009-09-28 23:59:09 +02:00
if ( $alt == 1 )
2009-06-14 18:25:23 +02:00
{
2009-09-28 23:59:09 +02:00
// This function MUST NOT contains call to syslog
//dol_syslog("Translate::Load loading alternate translation file (to complete ".$this->defaultlang."/".$newdomain.".lang file)", LOG_DEBUG);
$langofdir = 'en_US' ;
$this -> load ( $domain , $alt + 1 , $stopafterdirection , $langofdir );
2009-06-14 18:25:23 +02:00
}
2009-06-10 21:51:00 +02:00
2017-01-21 21:52:42 +01:00
// We already are the reference file. No more files to scan to complete.
2009-09-28 23:59:09 +02:00
if ( $alt == 2 )
{
2012-01-11 01:06:34 +01:00
if ( $fileread ) $this -> _tab_loaded [ $newdomain ] = 1 ; // Set domain file as loaded
2009-09-28 23:59:09 +02:00
2017-01-21 21:52:42 +01:00
if ( empty ( $this -> _tab_loaded [ $newdomain ])) $this -> _tab_loaded [ $newdomain ] = 2 ; // Set this file as found
2009-09-28 23:59:09 +02:00
}
2009-01-15 23:49:06 +01:00
2015-09-17 17:52:34 +02:00
// This part is deprecated and replaced with table llx_overwrite_trans
// Kept for backward compatibility.
2016-09-04 14:45:43 +02:00
if ( empty ( $loadfromfileonly ))
{
$overwritekey = 'MAIN_OVERWRITE_TRANS_' . $this -> defaultlang ;
if ( ! empty ( $conf -> global -> $overwritekey )) // Overwrite translation with key1:newstring1,key2:newstring2
2015-09-17 15:35:51 +02:00
{
2016-09-04 14:45:43 +02:00
// Overwrite translation with param MAIN_OVERWRITE_TRANS_xx_XX
$tmparray = explode ( ',' , $conf -> global -> $overwritekey );
foreach ( $tmparray as $tmp )
{
$tmparray2 = explode ( ':' , $tmp );
if ( ! empty ( $tmparray2 [ 1 ])) $this -> tab_translate [ $tmparray2 [ 0 ]] = $tmparray2 [ 1 ];
}
2015-09-17 15:35:51 +02:00
}
2017-06-09 09:25:15 +02:00
}
2015-09-17 17:52:34 +02:00
// Check to be sure that SeparatorDecimal differs from SeparatorThousand
2009-12-29 18:53:48 +01:00
if ( ! empty ( $this -> tab_translate [ " SeparatorDecimal " ]) && ! empty ( $this -> tab_translate [ " SeparatorThousand " ])
2010-01-13 17:26:19 +01:00
&& $this -> tab_translate [ " SeparatorDecimal " ] == $this -> tab_translate [ " SeparatorThousand " ]) $this -> tab_translate [ " SeparatorThousand " ] = '' ;
2009-12-16 22:42:42 +01:00
2008-03-31 17:17:39 +02:00
return 1 ;
2009-05-11 18:26:54 +02:00
}
2005-10-30 02:07:00 +01:00
2015-09-17 17:52:34 +02:00
/**
* Load translation key - value from database into a memory array .
* If data already loaded , do nothing .
* All data in translation array are stored in UTF - 8 format .
* tab_loaded is completed with $domain key .
* rule " we keep first entry found with we keep last entry found " so it is probably not what you want to do .
*
* Value for hash are : 1 : Loaded from disk , 2 : Not found , 3 : Loaded from cache
*
* @ param Database $db Database handler
* @ return int < 0 if KO , 0 if already loaded or loading not required , > 0 if OK
*/
function loadFromDatabase ( $db )
{
global $conf ;
$domain = 'database' ;
2017-06-09 09:25:15 +02:00
2015-09-17 17:52:34 +02:00
// Check parameters
if ( empty ( $db )) return 0 ; // Database handler can't be used
//dol_syslog("Translate::Load Start domain=".$domain." alt=".$alt." forcelangdir=".$forcelangdir." this->defaultlang=".$this->defaultlang);
$newdomain = $domain ;
$modulename = '' ;
// Check cache
if ( ! empty ( $this -> _tab_loaded [ $newdomain ])) // File already loaded for this domain
{
//dol_syslog("Translate::Load already loaded for newdomain=".$newdomain);
return 0 ;
}
$this -> _tab_loaded [ $newdomain ] = 1 ; // We want to be sure this function is called once only.
2017-06-09 09:25:15 +02:00
2015-09-17 17:52:34 +02:00
$fileread = 0 ;
$langofdir = ( empty ( $forcelangdir ) ? $this -> defaultlang : $forcelangdir );
// Redefine alt
$alt = 2 ;
if ( empty ( $langofdir )) // This may occurs when load is called without setting the language and without providing a value for forcelangdir
{
dol_syslog ( " Error: " . get_class ( $this ) . " ::Load was called but language was not set yet with langs->setDefaultLang(). Nothing will be loaded. " , LOG_WARNING );
return - 1 ;
}
// TODO Move cache read out of loop on dirs or at least filelangexists
$found = false ;
// Enable caching of lang file in memory (not by default)
$usecachekey = '' ;
// Using a memcached server
if ( ! empty ( $conf -> memcached -> enabled ) && ! empty ( $conf -> global -> MEMCACHED_SERVER ))
{
$usecachekey = $newdomain . '_' . $langofdir . '_' . md5 ( $file_lang ); // Should not contains special chars
}
// Using cache with shmop. Speed gain: 40ms - Memory overusage: 200ko (Size of session cache file)
else if ( isset ( $conf -> global -> MAIN_OPTIMIZE_SPEED ) && ( $conf -> global -> MAIN_OPTIMIZE_SPEED & 0x02 ))
{
$usecachekey = $newdomain ;
}
if ( $usecachekey )
{
//dol_syslog('Translate::Load we will cache result into usecachekey '.$usecachekey);
//global $aaa; $aaa+=1;
//print $aaa." ".$usecachekey."\n";
require_once DOL_DOCUMENT_ROOT . '/core/lib/memory.lib.php' ;
$tmparray = dol_getcache ( $usecachekey );
if ( is_array ( $tmparray ) && count ( $tmparray ))
{
$this -> tab_translate += $tmparray ; // Faster than array_merge($tmparray,$this->tab_translate). Note: If a valuer already exists into tab_translate, value into tmparaay is not added.
//print $newdomain."\n";
//var_dump($this->tab_translate);
2017-04-14 11:22:48 +02:00
$fileread = 1 ;
2015-09-17 17:52:34 +02:00
$found = true ; // Found in dolibarr PHP cache
}
}
2017-05-09 10:08:04 +02:00
if ( ! $found && ! empty ( $conf -> global -> MAIN_ENABLE_OVERWRITE_TRANSLATION ))
2015-09-17 17:52:34 +02:00
{
// Overwrite translation with database read
2017-06-09 09:25:15 +02:00
$sql = " SELECT transkey, transvalue FROM " . MAIN_DB_PREFIX . " overwrite_trans where lang=' " . $db -> escape ( $this -> defaultlang ) . " ' " ;
2015-09-17 17:52:34 +02:00
$resql = $db -> query ( $sql );
2017-06-09 09:25:15 +02:00
2015-09-17 17:52:34 +02:00
if ( $resql )
{
$num = $db -> num_rows ( $resql );
if ( $num )
{
if ( $usecachekey ) $tabtranslatedomain = array (); // To save lang content in cache
2017-06-09 09:25:15 +02:00
2015-09-17 17:52:34 +02:00
$i = 0 ;
while ( $i < $num ) // Ex: Need 225ms for all fgets on all lang file for Third party page. Same speed than file_get_contents
{
$obj = $db -> fetch_object ( $resql );
2017-06-09 09:25:15 +02:00
2015-09-17 17:52:34 +02:00
$key = $obj -> transkey ;
$value = $obj -> transvalue ;
2017-06-09 09:25:15 +02:00
2015-09-17 17:52:34 +02:00
//print "Domain=$domain, found a string for $tab[0] with value $tab[1]<br>";
if ( empty ( $this -> tab_translate [ $key ])) // If translation was already found, we must not continue, even if MAIN_FORCELANGDIR is set (MAIN_FORCELANGDIR is to replace lang dir, not to overwrite entries)
{
$value = trim ( preg_replace ( '/\\n/' , " \n " , $value ));
$this -> tab_translate [ $key ] = $value ;
if ( $usecachekey ) $tabtranslatedomain [ $key ] = $value ; // To save lang content in cache
}
2017-06-09 09:25:15 +02:00
2015-09-17 17:52:34 +02:00
$i ++ ;
}
2017-06-09 09:25:15 +02:00
2015-09-17 17:52:34 +02:00
$fileread = 1 ;
2017-06-09 09:25:15 +02:00
2015-09-17 17:52:34 +02:00
// TODO Move cache write out of loop on dirs
// To save lang content for usecachekey into cache
if ( $usecachekey && count ( $tabtranslatedomain ))
{
$ressetcache = dol_setcache ( $usecachekey , $tabtranslatedomain );
if ( $ressetcache < 0 )
{
$error = 'Failed to set cache for usecachekey=' . $usecachekey . ' result=' . $ressetcache ;
dol_syslog ( $error , LOG_ERR );
}
}
}
}
else
{
dol_print_error ( $db );
}
}
2017-04-14 11:22:48 +02:00
if ( $fileread ) $this -> _tab_loaded [ $newdomain ] = 1 ; // Set domain file as loaded
2015-09-17 17:52:34 +02:00
2017-04-14 11:22:48 +02:00
if ( empty ( $this -> _tab_loaded [ $newdomain ])) $this -> _tab_loaded [ $newdomain ] = 2 ; // Marque ce cas comme non trouve (no lines found for language)
2015-09-17 17:52:34 +02:00
return 1 ;
}
2017-06-09 09:25:15 +02:00
2009-08-25 16:36:03 +02:00
/**
2015-06-30 01:34:17 +02:00
* Return translated value of key for special keys ( " Currency... " , " Civility... " , ... ) .
* Search in lang file , then into database . Key must be any complete entry into lang file : CurrencyEUR , ...
2011-01-23 23:39:48 +01:00
* If not found , return key .
2014-08-01 14:26:13 +02:00
* The string return is not formated ( translated with transnoentitiesnoconv )
* NOTE : To avoid infinite loop ( getLabelFromKey -> transnoentities -> getTradFromKey ), if you modify this function ,
* check that getLabelFromKey is not called with same value than input .
2009-08-25 16:36:03 +02:00
*
2011-12-07 17:28:11 +01:00
* @ param string $key Key to translate
2014-08-01 14:26:13 +02:00
* @ return string Translated string ( translated with transnoentitiesnoconv )
2009-08-25 16:36:03 +02:00
*/
2012-10-04 09:44:04 +02:00
private function getTradFromKey ( $key )
2009-08-07 02:49:43 +02:00
{
2018-05-16 10:31:44 +02:00
global $conf , $db ;
2012-10-03 17:47:53 +02:00
2014-06-20 16:20:39 +02:00
if ( ! is_string ( $key )) return 'ErrorBadValueForParamNotAString' ; // Avoid multiple errors with code not using function correctly.
2009-08-07 02:49:43 +02:00
$newstr = $key ;
2015-06-30 01:34:17 +02:00
if ( preg_match ( '/^Civility([0-9A-Z]+)$/i' , $key , $reg ))
{
$newstr = $this -> getLabelFromKey ( $db , $reg [ 1 ], 'c_civility' , 'code' , 'label' );
}
elseif ( preg_match ( '/^Currency([A-Z][A-Z][A-Z])$/i' , $key , $reg ))
2009-08-07 02:49:43 +02:00
{
2012-10-04 09:44:04 +02:00
$newstr = $this -> getLabelFromKey ( $db , $reg [ 1 ], 'c_currencies' , 'code_iso' , 'label' );
2009-08-07 02:49:43 +02:00
}
2015-06-30 01:34:17 +02:00
elseif ( preg_match ( '/^SendingMethod([0-9A-Z]+)$/i' , $key , $reg ))
2009-08-07 02:49:43 +02:00
{
2012-10-04 09:44:04 +02:00
$newstr = $this -> getLabelFromKey ( $db , $reg [ 1 ], 'c_shipment_mode' , 'code' , 'libelle' );
2009-08-07 02:49:43 +02:00
}
2015-06-30 01:34:17 +02:00
elseif ( preg_match ( '/^PaymentTypeShort([0-9A-Z]+)$/i' , $key , $reg ))
2010-10-18 20:18:12 +02:00
{
2017-10-03 17:41:22 +02:00
$newstr = $this -> getLabelFromKey ( $db , $reg [ 1 ], 'c_paiement' , 'code' , 'libelle' , '' , 1 );
2015-06-30 01:34:17 +02:00
}
elseif ( preg_match ( '/^OppStatus([0-9A-Z]+)$/i' , $key , $reg ))
{
$newstr = $this -> getLabelFromKey ( $db , $reg [ 1 ], 'c_lead_status' , 'code' , 'label' );
2011-01-23 23:39:48 +01:00
}
2015-06-30 01:34:17 +02:00
elseif ( preg_match ( '/^OrderSource([0-9A-Z]+)$/i' , $key , $reg ))
2011-03-08 11:09:15 +01:00
{
2015-06-30 01:34:17 +02:00
// TODO OrderSourceX must be replaced with content of table llx_c_input_reason or llx_c_input_method
2011-03-08 11:09:15 +01:00
//$newstr=$this->getLabelFromKey($db,$reg[1],'c_ordersource','code','label');
}
2018-05-16 10:31:44 +02:00
2018-05-25 11:07:11 +02:00
if ( ! empty ( $conf -> global -> MAIN_FEATURES_LEVEL ) && $conf -> global -> MAIN_FEATURES_LEVEL >= 2 ) dol_syslog ( __METHOD__ . " missing translation for key ' " . $newstr . " ' in " . $_SERVER [ " PHP_SELF " ], LOG_DEBUG );
2018-05-16 10:31:44 +02:00
2011-01-23 23:39:48 +01:00
return $newstr ;
2009-08-07 02:49:43 +02:00
}
2009-05-11 18:26:54 +02:00
/**
2010-10-18 20:18:12 +02:00
* Return text translated of text received as parameter ( and encode it into HTML )
2009-05-11 18:26:54 +02:00
* Si il n ' y a pas de correspondance pour ce texte , on cherche dans fichier alternatif
* et si toujours pas trouve , il est retourne tel quel
* Les parametres de cette methode peuvent contenir de balises HTML .
2011-08-16 01:17:14 +02:00
*
2011-12-07 17:28:11 +01:00
* @ param string $key Key to translate
* @ param string $param1 chaine de param1
* @ param string $param2 chaine de param2
* @ param string $param3 chaine de param3
* @ param string $param4 chaine de param4
2011-12-07 18:10:24 +01:00
* @ param int $maxsize Max length of text
2011-12-07 17:28:11 +01:00
* @ return string Translated string ( encoded into HTML entities and UTF8 )
2009-05-11 18:26:54 +02:00
*/
function trans ( $key , $param1 = '' , $param2 = '' , $param3 = '' , $param4 = '' , $maxsize = 0 )
{
2011-12-12 19:46:46 +01:00
global $conf ;
2011-08-27 18:41:30 +02:00
if ( ! empty ( $this -> tab_translate [ $key ])) // Translation is available
2009-05-11 18:26:54 +02:00
{
2011-03-08 16:14:42 +01:00
$str = $this -> tab_translate [ $key ];
2010-06-26 12:14:54 +02:00
2015-10-13 13:27:44 +02:00
// Make some string replacement after translation
2015-10-19 13:23:45 +02:00
$replacekey = 'MAIN_REPLACE_TRANS_' . $this -> defaultlang ;
if ( ! empty ( $conf -> global -> $replacekey )) // Replacement translation variable with string1:newstring1;string2:newstring2
2015-10-13 13:27:44 +02:00
{
$tmparray = explode ( ';' , $conf -> global -> $replacekey );
foreach ( $tmparray as $tmp )
{
$tmparray2 = explode ( ':' , $tmp );
$str = preg_replace ( '/' . preg_quote ( $tmparray2 [ 0 ]) . '/' , $tmparray2 [ 1 ], $str );
}
}
2017-06-09 09:25:15 +02:00
if ( ! preg_match ( '/^Format/' , $key ))
2015-08-27 23:49:25 +02:00
{
//print $str;
$str = sprintf ( $str , $param1 , $param2 , $param3 , $param4 ); // Replace %s and %d except for FormatXXX strings.
}
2011-08-27 18:41:30 +02:00
2009-05-11 18:26:54 +02:00
if ( $maxsize ) $str = dol_trunc ( $str , $maxsize );
2011-03-08 16:16:03 +01:00
// We replace some HTML tags by __xx__ to avoid having them encoded by htmlentities
2011-03-08 16:14:42 +01:00
$str = str_replace ( array ( '<' , '>' , '"' ,), array ( '__lt__' , '__gt__' , '__quot__' ), $str );
2009-05-11 18:26:54 +02:00
2011-03-08 16:16:03 +01:00
// Crypt string into HTML
2017-10-26 10:43:47 +02:00
$str = htmlentities ( $str , ENT_COMPAT , $this -> charset_output ); // Do not convert simple quotes in translation (strings in html are enmbraced by "). Use dol_escape_htmltag around text in HTML content
2009-05-11 18:26:54 +02:00
2011-03-08 16:16:03 +01:00
// Restore HTML tags
2011-03-08 16:14:42 +01:00
$str = str_replace ( array ( '__lt__' , '__gt__' , '__quot__' ), array ( '<' , '>' , '"' ,), $str );
2011-12-12 19:46:46 +01:00
2011-03-08 16:14:42 +01:00
return $str ;
2009-05-11 18:26:54 +02:00
}
2009-05-23 00:18:59 +02:00
else // Translation is not available
2009-05-11 18:26:54 +02:00
{
2017-12-09 15:35:01 +01:00
//if ($key[0] == '$') { return dol_eval($key,1); }
2011-12-07 18:10:24 +01:00
return $this -> getTradFromKey ( $key );
2007-05-26 00:23:03 +02:00
}
2009-05-11 18:26:54 +02:00
}
2008-07-28 11:09:03 +02:00
2009-01-15 23:49:06 +01:00
2008-10-20 03:05:41 +02:00
/**
2011-03-08 16:14:42 +01:00
* Return translated value of a text string
2009-05-11 18:26:54 +02:00
* Si il n ' y a pas de correspondance pour ce texte , on cherche dans fichier alternatif
* et si toujours pas trouve , il est retourne tel quel .
* Parameters of this method must not contains any HTML tags .
2011-08-16 01:17:14 +02:00
*
2011-12-07 18:10:24 +01:00
* @ param string $key Key to translate
* @ param string $param1 chaine de param1
* @ param string $param2 chaine de param2
* @ param string $param3 chaine de param3
* @ param string $param4 chaine de param4
* @ return string Translated string ( encoded into UTF8 )
2009-05-11 18:26:54 +02:00
*/
function transnoentities ( $key , $param1 = '' , $param2 = '' , $param3 = '' , $param4 = '' )
{
2011-12-07 18:10:24 +01:00
return $this -> convToOutputCharset ( $this -> transnoentitiesnoconv ( $key , $param1 , $param2 , $param3 , $param4 ));
2009-05-11 18:26:54 +02:00
}
/**
2010-11-13 02:58:19 +01:00
* Return translated value of a text string
2009-05-11 18:26:54 +02:00
* Si il n ' y a pas de correspondance pour ce texte , on cherche dans fichier alternatif
* et si toujours pas trouve , il est retourne tel quel .
* No convert to encoding charset of lang object is done .
* Parameters of this method must not contains any HTML tags .
2011-08-16 01:17:14 +02:00
*
2011-12-07 18:10:24 +01:00
* @ param string $key Key to translate
* @ param string $param1 chaine de param1
* @ param string $param2 chaine de param2
* @ param string $param3 chaine de param3
* @ param string $param4 chaine de param4
* @ return string Translated string
2009-05-11 18:26:54 +02:00
*/
function transnoentitiesnoconv ( $key , $param1 = '' , $param2 = '' , $param3 = '' , $param4 = '' )
{
2012-11-02 15:41:09 +01:00
global $conf ;
2012-11-04 21:19:12 +01:00
2011-12-07 18:10:24 +01:00
if ( ! empty ( $this -> tab_translate [ $key ])) // Translation is available
2009-05-11 18:26:54 +02:00
{
2011-12-07 18:10:24 +01:00
$str = $this -> tab_translate [ $key ];
2015-10-19 13:23:45 +02:00
// Make some string replacement after translation
$replacekey = 'MAIN_REPLACE_TRANS_' . $this -> defaultlang ;
if ( ! empty ( $conf -> global -> $replacekey )) // Replacement translation variable with string1:newstring1;string2:newstring2
2012-11-02 15:41:09 +01:00
{
2015-10-19 13:23:45 +02:00
$tmparray = explode ( ';' , $conf -> global -> $replacekey );
2012-11-02 15:41:09 +01:00
foreach ( $tmparray as $tmp )
{
$tmparray2 = explode ( ':' , $tmp );
2015-10-19 13:23:45 +02:00
$str = preg_replace ( '/' . preg_quote ( $tmparray2 [ 0 ]) . '/' , $tmparray2 [ 1 ], $str );
2012-11-02 15:41:09 +01:00
}
2017-06-09 09:25:15 +02:00
}
2012-11-04 21:19:12 +01:00
2017-06-09 09:25:15 +02:00
if ( ! preg_match ( '/^Format/' , $key ))
2015-08-27 23:49:25 +02:00
{
//print $str;
$str = sprintf ( $str , $param1 , $param2 , $param3 , $param4 ); // Replace %s and %d except for FormatXXX strings.
}
2012-11-04 21:19:12 +01:00
return $str ;
2009-08-07 02:49:43 +02:00
}
else
{
2012-11-04 21:19:12 +01:00
if ( $key [ 0 ] == '$' ) { return dol_eval ( $key , 1 ); }
return $this -> getTradFromKey ( $key );
2009-05-11 18:26:54 +02:00
}
}
/**
2010-11-13 02:58:19 +01:00
* Return translation of a key depending on country
2011-08-16 01:17:14 +02:00
*
2012-01-14 14:27:27 +01:00
* @ param string $str string root to translate
* @ param string $countrycode country code ( FR , ... )
* @ return string translated string
2009-05-11 18:26:54 +02:00
*/
function transcountry ( $str , $countrycode )
{
if ( $this -> tab_translate [ " $str $countrycode " ]) return $this -> trans ( " $str $countrycode " );
else return $this -> trans ( $str );
}
/**
2010-09-15 10:36:13 +02:00
* Retourne la version traduite du texte passe en parametre complete du code pays
2011-08-16 01:17:14 +02:00
*
2012-01-14 14:27:27 +01:00
* @ param string $str string root to translate
* @ param string $countrycode country code ( FR , ... )
* @ return string translated string
2009-05-11 18:26:54 +02:00
*/
function transcountrynoentities ( $str , $countrycode )
{
if ( $this -> tab_translate [ " $str $countrycode " ]) return $this -> transnoentities ( " $str $countrycode " );
else return $this -> transnoentities ( $str );
}
/**
2010-11-13 02:58:19 +01:00
* Convert a string into output charset ( this -> charset_output that should be defined to conf -> file -> character_set_client )
2011-08-16 01:17:14 +02:00
*
2012-01-14 14:27:27 +01:00
* @ param string $str String to convert
* @ param string $pagecodefrom Page code of src string
* @ return string Converted string
2009-05-11 18:26:54 +02:00
*/
function convToOutputCharset ( $str , $pagecodefrom = 'UTF-8' )
{
if ( $pagecodefrom == 'ISO-8859-1' && $this -> charset_output == 'UTF-8' ) $str = utf8_encode ( $str );
2010-04-28 13:14:53 +02:00
if ( $pagecodefrom == 'UTF-8' && $this -> charset_output == 'ISO-8859-1' ) $str = utf8_decode ( str_replace ( '€' , chr ( 128 ), $str ));
2007-05-26 00:23:03 +02:00
return $str ;
2009-05-11 18:26:54 +02:00
}
/**
2010-11-13 02:58:19 +01:00
* Return list of all available languages
2011-08-16 01:17:14 +02:00
*
2012-01-14 14:27:27 +01:00
* @ param string $langdir Directory to scan
2015-03-06 03:10:01 +01:00
* @ param integer $maxlength Max length for each value in combo box ( will be truncated )
2016-02-23 19:50:33 +01:00
* @ param int $usecode 1 = Show code instead of country name for language variant , 2 = Show only code
2012-01-14 14:27:27 +01:00
* @ return array List of languages
2009-05-11 18:26:54 +02:00
*/
2011-08-02 00:03:50 +02:00
function get_available_languages ( $langdir = DOL_DOCUMENT_ROOT , $maxlength = 0 , $usecode = 0 )
2009-05-11 18:26:54 +02:00
{
2010-03-03 08:42:11 +01:00
global $conf ;
2010-05-08 04:16:29 +02:00
2009-05-11 18:26:54 +02:00
// We scan directory langs to detect available languages
2010-02-18 13:58:42 +01:00
$handle = opendir ( $langdir . " /langs " );
2009-05-11 18:26:54 +02:00
$langs_available = array ();
2010-02-18 13:58:42 +01:00
while ( $dir = trim ( readdir ( $handle )))
2009-05-11 18:26:54 +02:00
{
2010-02-18 13:58:42 +01:00
if ( preg_match ( '/^[a-z]+_[A-Z]+/i' , $dir ))
2009-05-11 18:26:54 +02:00
{
2010-02-18 13:58:42 +01:00
$this -> load ( " languages " );
2010-02-20 14:15:28 +01:00
2016-02-23 19:50:33 +01:00
if ( $usecode == 2 )
2010-03-03 08:42:11 +01:00
{
2016-02-23 19:50:33 +01:00
$langs_available [ $dir ] = $dir ;
}
if ( $usecode == 1 || ! empty ( $conf -> global -> MAIN_SHOW_LANGUAGE_CODE ))
{
$langs_available [ $dir ] = $dir . ': ' . dol_trunc ( $this -> trans ( 'Language_' . $dir ), $maxlength );
2010-03-03 08:42:11 +01:00
}
else
{
$langs_available [ $dir ] = $this -> trans ( 'Language_' . $dir );
}
2009-05-11 18:26:54 +02:00
}
}
return $langs_available ;
}
/**
2010-11-13 02:58:19 +01:00
* Return if a filename $filename exists for current language ( or alternate language )
2011-08-16 01:17:14 +02:00
*
2012-01-14 14:27:27 +01:00
* @ param string $filename Language filename to search
2015-03-06 03:10:01 +01:00
* @ param integer $searchalt Search also alernate language file
2012-01-14 14:27:27 +01:00
* @ return boolean true if exists and readable
2009-05-11 18:26:54 +02:00
*/
function file_exists ( $filename , $searchalt = 0 )
{
// Test si fichier dans repertoire de la langue
2008-12-12 03:16:14 +01:00
foreach ( $this -> dir as $searchdir )
{
2009-12-17 16:44:51 +01:00
if ( is_readable ( dol_osencode ( $searchdir . " /langs/ " . $this -> defaultlang . " / " . $filename ))) return true ;
2009-05-11 18:26:54 +02:00
2010-01-13 17:26:19 +01:00
if ( $searchalt )
2009-12-17 16:44:51 +01:00
{
2009-05-11 18:26:54 +02:00
// Test si fichier dans repertoire de la langue alternative
2009-12-17 16:44:51 +01:00
if ( $this -> defaultlang != " en_US " ) $filenamealt = $searchdir . " /langs/en_US/ " . $filename ;
2014-08-08 10:50:37 +02:00
//else $filenamealt = $searchdir."/langs/fr_FR/".$filename;
2009-12-17 16:44:51 +01:00
if ( is_readable ( dol_osencode ( $filenamealt ))) return true ;
2009-05-11 18:26:54 +02:00
}
2008-12-12 03:16:14 +01:00
}
2009-01-15 23:49:06 +01:00
2009-05-11 18:26:54 +02:00
return false ;
}
2009-08-25 16:36:03 +02:00
/**
2010-11-13 02:58:19 +01:00
* Return full text translated to language label for a key . Store key - label in a cache .
* This function need module " numberwords " to be installed . If not it will return
2011-08-16 01:17:14 +02:00
* same number ( this module is not provided by default as it use non GPL source code ) .
*
2012-01-14 14:27:27 +01:00
* @ param int $number Number to encode in full text
* @ param int $isamount 1 = It 's an amount, 0=it' s just a number
* @ return string Label translated in UTF8 ( but without entities )
* 10 if setDefaultLang was en_US => ten
* 123 if setDefaultLang was fr_FR => cent vingt trois
2009-08-25 16:36:03 +02:00
*/
function getLabelFromNumber ( $number , $isamount = 0 )
{
2009-08-25 22:57:54 +02:00
global $conf ;
$newnumber = $number ;
2012-02-22 16:18:03 +01:00
2012-04-28 17:01:25 +02:00
$dirsubstitutions = array_merge ( array (), $conf -> modules_parts [ 'substitutions' ]);
2012-02-22 16:18:03 +01:00
foreach ( $dirsubstitutions as $reldir )
2009-08-25 22:57:54 +02:00
{
2012-02-22 16:18:03 +01:00
$dir = dol_buildpath ( $reldir , 0 );
$newdir = dol_osencode ( $dir );
// Check if directory exists
2013-03-08 01:50:16 +01:00
if ( ! is_dir ( $newdir )) continue ; // We must not use dol_is_dir here, function may not be loaded
2012-02-22 16:18:03 +01:00
2009-08-25 22:57:54 +02:00
$fonc = 'numberwords' ;
2012-02-22 16:18:03 +01:00
if ( file_exists ( $newdir . '/functions_' . $fonc . '.lib.php' ))
2009-08-25 22:57:54 +02:00
{
2012-08-23 02:04:35 +02:00
include_once $newdir . '/functions_' . $fonc . '.lib.php' ;
2009-08-25 22:57:54 +02:00
$newnumber = numberwords_getLabelFromNumber ( $this , $number , $isamount );
break ;
}
}
2009-08-25 16:36:03 +02:00
2009-08-25 22:57:54 +02:00
return $newnumber ;
2009-08-25 16:36:03 +02:00
}
2009-05-11 18:26:54 +02:00
/**
2012-10-04 09:44:04 +02:00
* Return a label for a key .
* Search into translation array , then into cache , then if still not found , search into database .
* Store key - label found into cache variable $this -> cache_labels to save SQL requests to get labels .
2011-08-16 01:17:14 +02:00
*
2014-05-03 13:42:34 +02:00
* @ param DoliDB $db Database handler
2013-05-12 17:09:48 +02:00
* @ param string $key Translation key to get label ( key in language file )
2012-10-03 17:47:53 +02:00
* @ param string $tablename Table name without prefix
* @ param string $fieldkey Field for key
* @ param string $fieldlabel Field for label
2013-05-12 17:09:48 +02:00
* @ param string $keyforselect Use another value than the translation key for the where into select
2017-10-03 17:41:22 +02:00
* @ param int $filteronentity Use a filter on entity
2012-10-03 17:47:53 +02:00
* @ return string Label in UTF8 ( but without entities )
2013-05-12 17:09:48 +02:00
* @ see dol_getIdFromCode
2009-05-11 18:26:54 +02:00
*/
2017-10-03 17:41:22 +02:00
function getLabelFromKey ( $db , $key , $tablename , $fieldkey , $fieldlabel , $keyforselect = '' , $filteronentity = 0 )
2009-05-11 18:26:54 +02:00
{
// If key empty
2008-05-03 23:44:32 +02:00
if ( $key == '' ) return '' ;
2012-10-03 17:47:53 +02:00
//print 'param: '.$key.'-'.$keydatabase.'-'.$this->trans($key); exit;
2008-06-30 21:34:53 +02:00
2014-06-20 16:20:39 +02:00
// Check if a translation is available (this can call getTradFromKey)
2016-05-19 21:12:09 +02:00
$tmp = $this -> transnoentitiesnoconv ( $key );
if ( $tmp != $key && $tmp != 'ErrorBadValueForParamNotAString' )
2009-05-11 18:26:54 +02:00
{
2016-05-19 21:12:09 +02:00
return $tmp ; // Found in language array
2009-05-11 18:26:54 +02:00
}
2009-01-15 23:49:06 +01:00
2008-06-30 21:34:53 +02:00
// Check in cache
2009-05-11 18:26:54 +02:00
if ( isset ( $this -> cache_labels [ $tablename ][ $key ])) // Can be defined to 0 or ''
{
return $this -> cache_labels [ $tablename ][ $key ]; // Found in cache
}
$sql = " SELECT " . $fieldlabel . " as label " ;
$sql .= " FROM " . MAIN_DB_PREFIX . $tablename ;
2018-03-15 02:12:01 +01:00
$sql .= " WHERE " . $fieldkey . " = ' " . $db -> escape ( $keyforselect ? $keyforselect : $key ) . " ' " ;
2017-10-03 17:41:22 +02:00
if ( $filteronentity ) $sql .= " AND entity IN ( " . getEntity ( $tablename ) . ')' ;
2014-06-13 01:34:39 +02:00
dol_syslog ( get_class ( $this ) . '::getLabelFromKey' , LOG_DEBUG );
2009-05-11 18:26:54 +02:00
$resql = $db -> query ( $sql );
if ( $resql )
{
$obj = $db -> fetch_object ( $resql );
if ( $obj ) $this -> cache_labels [ $tablename ][ $key ] = $obj -> label ;
2010-10-18 20:18:12 +02:00
else $this -> cache_labels [ $tablename ][ $key ] = $key ;
2009-05-11 18:26:54 +02:00
$db -> free ( $resql );
return $this -> cache_labels [ $tablename ][ $key ];
}
else
{
2008-03-16 15:52:31 +01:00
$this -> error = $db -> lasterror ();
2009-05-11 18:26:54 +02:00
return - 1 ;
}
}
2008-10-20 03:05:41 +02:00
2013-01-18 15:57:11 +01:00
/**
* Return a currency code into its symbol
*
2013-04-04 13:58:33 +02:00
* @ param string $currency_code Currency Code
2013-01-18 15:57:11 +01:00
* @ param string $amount If not '' , show currency + amount according to langs ( $ 10 , 10 € ) .
* @ return string Amount + Currency symbol encoded into UTF8
2014-10-16 01:26:44 +02:00
* @ deprecated Use method price to output a price
2015-04-23 23:21:06 +02:00
* @ see price ()
2013-01-18 15:57:11 +01:00
*/
function getCurrencyAmount ( $currency_code , $amount )
{
2014-04-23 15:24:09 +02:00
$symbol = $this -> getCurrencySymbol ( $currency_code );
2013-01-18 15:57:11 +01:00
if ( in_array ( $currency_code , array ( 'USD' ))) return $symbol . $amount ;
else return $amount . $symbol ;
}
2013-01-19 16:29:16 +01:00
/**
2017-06-09 09:25:15 +02:00
* Return a currency code into its symbol .
2016-04-30 14:09:00 +02:00
* If mb_convert_encoding is not available , return currency code .
2013-01-19 16:29:16 +01:00
*
2013-01-18 15:57:11 +01:00
* @ param string $currency_code Currency code
2015-03-06 03:10:01 +01:00
* @ param integer $forceloadall 1 = Force to load all currencies into cache . We know we need to use all of them . By default read and cache only required currency .
2013-01-19 16:29:16 +01:00
* @ return string Currency symbol encoded into UTF8
*/
function getCurrencySymbol ( $currency_code , $forceloadall = 0 )
{
$currency_sign = '' ; // By default return iso code
2013-01-18 15:57:11 +01:00
if ( function_exists ( " mb_convert_encoding " ))
{
2014-05-14 12:19:45 +02:00
$this -> loadCacheCurrencies ( $forceloadall ? '' : $currency_code );
2013-01-18 15:57:11 +01:00
if ( isset ( $this -> cache_currencies [ $currency_code ]) && ! empty ( $this -> cache_currencies [ $currency_code ][ 'unicode' ]) && is_array ( $this -> cache_currencies [ $currency_code ][ 'unicode' ]))
2013-01-19 16:29:16 +01:00
{
foreach ( $this -> cache_currencies [ $currency_code ][ 'unicode' ] as $unicode )
{
$currency_sign .= mb_convert_encoding ( " &# { $unicode } ; " , " UTF-8 " , 'HTML-ENTITIES' );
2013-01-18 15:57:11 +01:00
}
2013-01-19 16:29:16 +01:00
}
}
return ( $currency_sign ? $currency_sign : $currency_code );
2013-01-18 15:57:11 +01:00
}
2013-01-19 16:29:16 +01:00
/**
2014-05-01 16:11:29 +02:00
* Load into the cache this -> cache_currencies , all currencies
2013-01-18 15:57:11 +01:00
*
2013-01-19 16:29:16 +01:00
* @ param string $currency_code Get only currency . Get all if '' .
* @ return int Nb of loaded lines , 0 if already loaded , < 0 if KO
*/
2014-05-14 12:19:45 +02:00
public function loadCacheCurrencies ( $currency_code )
2013-01-18 15:57:11 +01:00
{
global $db ;
2013-01-19 16:29:16 +01:00
2017-04-14 18:08:02 +02:00
if ( $this -> cache_currencies_all_loaded ) return 0 ; // Cache already loaded for all
if ( ! empty ( $currency_code ) && isset ( $this -> cache_currencies [ $currency_code ])) return 0 ; // Cache already loaded for the currency
2013-01-19 16:29:16 +01:00
$sql = " SELECT code_iso, label, unicode " ;
$sql .= " FROM " . MAIN_DB_PREFIX . " c_currencies " ;
2013-01-18 15:57:11 +01:00
$sql .= " WHERE active = 1 " ;
2018-03-15 02:12:01 +01:00
if ( ! empty ( $currency_code )) $sql .= " AND code_iso = ' " . $db -> escape ( $currency_code ) . " ' " ;
2013-01-19 16:29:16 +01:00
//$sql.= " ORDER BY code_iso ASC"; // Not required, a sort is done later
2014-06-13 01:34:39 +02:00
dol_syslog ( get_class ( $this ) . '::loadCacheCurrencies' , LOG_DEBUG );
2013-01-19 16:29:16 +01:00
$resql = $db -> query ( $sql );
if ( $resql )
{
2013-01-18 15:57:11 +01:00
$this -> load ( " dict " );
$label = array ();
2017-04-14 18:08:02 +02:00
if ( ! empty ( $currency_code )) foreach ( $this -> cache_currencies as $key => $val ) $label [ $key ] = $val [ 'label' ]; // Label in already loaded cache
2013-01-18 15:57:11 +01:00
2013-01-19 16:29:16 +01:00
$num = $db -> num_rows ( $resql );
$i = 0 ;
while ( $i < $num )
{
$obj = $db -> fetch_object ( $resql );
// Si traduction existe, on l'utilise, sinon on prend le libelle par defaut
$this -> cache_currencies [ $obj -> code_iso ][ 'label' ] = ( $obj -> code_iso && $this -> trans ( " Currency " . $obj -> code_iso ) != " Currency " . $obj -> code_iso ? $this -> trans ( " Currency " . $obj -> code_iso ) : ( $obj -> label != '-' ? $obj -> label : '' ));
$this -> cache_currencies [ $obj -> code_iso ][ 'unicode' ] = ( array ) json_decode ( $obj -> unicode , true );
$label [ $obj -> code_iso ] = $this -> cache_currencies [ $obj -> code_iso ][ 'label' ];
$i ++ ;
}
2017-04-14 18:08:02 +02:00
if ( empty ( $currency_code )) $this -> cache_currencies_all_loaded = true ;
2013-06-19 23:46:18 +02:00
//print count($label).' '.count($this->cache_currencies);
2017-04-14 18:08:02 +02:00
// Resort cache
2013-01-19 16:29:16 +01:00
array_multisort ( $label , SORT_ASC , $this -> cache_currencies );
2013-06-19 23:46:18 +02:00
//var_dump($this->cache_currencies); $this->cache_currencies is now sorted onto label
2013-01-19 16:29:16 +01:00
return $num ;
}
else
{
dol_print_error ( $db );
return - 1 ;
}
2013-01-18 15:57:11 +01:00
}
2013-10-08 09:17:04 +02:00
2014-05-01 16:11:29 +02:00
/**
2015-10-19 13:23:45 +02:00
* Return an array with content of all loaded translation keys ( found into this -> tab_translate ) so
* we get a substitution array we can use for substitutions ( for mail or ODT generation for example )
2014-05-01 16:11:29 +02:00
*
* @ return array Array of translation keys lang_key => string_translation_loaded
*/
function get_translations_for_substitutions ()
{
2013-10-08 09:17:04 +02:00
$substitutionarray = array ();
2013-10-11 10:01:47 +02:00
2013-10-08 09:17:04 +02:00
foreach ( $this -> tab_translate as $code => $label ) {
$substitutionarray [ 'lang_' . $code ] = $label ;
2018-02-24 14:23:52 +01:00
$substitutionarray [ '__(' . $code . ')__' ] = $label ;
2013-10-08 09:17:04 +02:00
}
2013-10-11 10:01:47 +02:00
2013-10-08 09:17:04 +02:00
return $substitutionarray ;
}
2003-05-02 12:33:06 +02:00
}