36 public $charset_output =
'UTF-8';
38 public $tab_translate = array();
39 private $_tab_loaded = array();
41 public $cache_labels = array();
42 public $cache_currencies = array();
43 private $cache_currencies_all_loaded =
false;
46 public $errors = array();
57 if (!empty($conf->file->character_set_client)) {
58 $this->charset_output = $conf->file->character_set_client;
61 $this->dir = array($dir);
63 $this->dir = $conf->file->dol_document_root;
81 if (!empty($conf->global->MAIN_FORCELANGDIR)) {
84 foreach ($conf->file->dol_document_root as $dir) {
85 $newdir = $dir.$conf->global->MAIN_FORCELANGDIR;
86 if (!in_array($newdir, $this->dir)) {
87 $more[
'module_'.$i] = $newdir;
91 $this->dir = array_merge($more, $this->dir);
94 $this->origlang = $srclang;
96 if (empty($srclang) || $srclang ==
'auto') {
98 $langpref = empty($_SERVER[
'HTTP_ACCEPT_LANGUAGE']) ?
'' : $_SERVER[
'HTTP_ACCEPT_LANGUAGE'];
99 $langpref = preg_replace(
"/;([^,]*)/i",
"", $langpref);
100 $langpref = str_replace(
"-",
"_", $langpref);
101 $langlist = preg_split(
"/[;,]/", $langpref);
102 $codetouse = preg_replace(
'/[^_a-zA-Z]/',
'', $langlist[0]);
104 $codetouse = $srclang;
108 $langpart = explode(
"_", $codetouse);
110 if (!empty($langpart[1])) {
112 $longforshort = array(
'ar'=>
'ar_SA');
113 $longforshortexcep = array(
'ar_EG');
114 if (isset($longforshort[strtolower($langpart[0])]) && !in_array($codetouse, $longforshortexcep)) {
115 $srclang = $longforshort[strtolower($langpart[0])];
116 } elseif (!is_numeric($langpart[1])) {
117 $srclang = strtolower($langpart[0]).
"_".strtoupper($langpart[1]);
118 $longforlong = array(
'no_nb'=>
'nb_NO');
119 if (isset($longforlong[strtolower($srclang)])) {
120 $srclang = $longforlong[strtolower($srclang)];
123 $srclang = strtolower($langpart[0]).
"_".strtoupper($langpart[0]);
127 $longforshort = array(
128 'am'=>
'am_ET',
'ar'=>
'ar_SA',
'bn'=>
'bn_DB',
'el'=>
'el_GR',
'ca'=>
'ca_ES',
'cs'=>
'cs_CZ',
'en'=>
'en_US',
'fa'=>
'fa_IR',
129 'gl'=>
'gl_ES',
'he'=>
'he_IL',
'hi'=>
'hi_IN',
'ja'=>
'ja_JP',
130 'ka'=>
'ka_GE',
'km'=>
'km_KH',
'kn'=>
'kn_IN',
'ko'=>
'ko_KR',
'lo'=>
'lo_LA',
'nb'=>
'nb_NO',
'no'=>
'nb_NO',
'ne'=>
'ne_NP',
131 'sl'=>
'sl_SI',
'sq'=>
'sq_AL',
'sr'=>
'sr_RS',
'sv'=>
'sv_SE',
'uk'=>
'uk_UA',
'vi'=>
'vi_VN',
'zh'=>
'zh_CN'
133 if (isset($longforshort[strtolower($langpart[0])])) {
134 $srclang = $longforshort[strtolower($langpart[0])];
135 } elseif (!empty($langpart[0])) {
136 $srclang = strtolower($langpart[0]).
"_".strtoupper($langpart[0]);
142 $this->defaultlang = $srclang;
143 $this->shortlang = substr($srclang, 0, 2);
158 return $this->defaultlang;
160 return substr($this->defaultlang, 0, 2);
173 foreach ($domains as $domain) {
174 $this->
load($domain);
199 public function load($domain, $alt = 0, $stopafterdirection = 0, $forcelangdir =
'', $loadfromfileonly = 0, $forceloadifalreadynotfound = 0)
206 if (empty($domain)) {
210 if ($this->defaultlang ===
'none_NONE') {
216 if (empty($loadfromfileonly) && count($this->tab_translate) == 0) {
221 $newdomain = $domain;
226 if (preg_match(
'/^([^@]+)@([^@]+)$/i', $domain, $regs)) {
227 $newdomain = $regs[1];
228 $modulename = $regs[2];
232 if (!empty($this->_tab_loaded[$newdomain])
233 && ($this->_tab_loaded[$newdomain] != 2 || empty($forceloadifalreadynotfound))) {
239 $langofdir = (empty($forcelangdir) ? $this->defaultlang : $forcelangdir);
242 $langarray = explode(
'_', $langofdir);
243 if ($alt < 1 && isset($langarray[1]) && (strtolower($langarray[0]) == strtolower($langarray[1]) || in_array(strtolower($langofdir), array(
'el_gr')))) {
246 if ($alt < 2 && strtolower($langofdir) ==
'en_us') {
250 if (empty($langofdir)) {
251 dol_syslog(
"Error: ".get_class($this).
"::load was called for domain=".$domain.
" but language was not set yet with langs->setDefaultLang(). Nothing will be loaded.", LOG_WARNING);
255 foreach ($this->dir as $searchdir) {
257 $file_lang = $searchdir.($modulename ?
'/'.$modulename :
'').
"/langs/".$langofdir.
"/".$newdomain.
".lang";
260 $filelangexists = is_file($file_lang_osencoded);
265 if ($filelangexists) {
272 if (!empty($conf->memcached->enabled) && !empty($conf->global->MEMCACHED_SERVER)) {
273 $usecachekey = $newdomain.
'_'.$langofdir.
'_'.md5($file_lang);
274 } elseif (isset($conf->global->MAIN_OPTIMIZE_SPEED) && ($conf->global->MAIN_OPTIMIZE_SPEED & 0x02)) {
276 $usecachekey = $newdomain;
283 require_once DOL_DOCUMENT_ROOT.
'/core/lib/memory.lib.php';
285 if (is_array($tmparray) && count($tmparray)) {
286 $this->tab_translate += $tmparray;
297 if ($fp = @fopen($file_lang,
"rt")) {
299 $tabtranslatedomain = array();
307 while ($line = fscanf($fp,
"%[^= ]%*[ =]%[^\n\r]")) {
308 if (isset($line[1])) {
309 list($key, $value) = $line;
312 if (empty($this->tab_translate[$key])) {
313 if ($key ==
'DIRECTION') {
314 if ($alt < 2 || empty($this->tab_translate[$key])) {
315 $this->tab_translate[$key] = $value;
316 if ($stopafterdirection) {
318 } elseif ($usecachekey) {
319 $tabtranslatedomain[$key] = $value;
322 } elseif ($key[0] ==
'#') {
326 $this->tab_translate[$key] = str_replace(array(
'\\n',
'\\\\s'), array(
"\n",
'\s'), $value);
328 $tabtranslatedomain[$key] = $value;
339 if ($usecachekey && count($tabtranslatedomain)) {
340 $ressetcache =
dol_setcache($usecachekey, $tabtranslatedomain);
341 if ($ressetcache < 0) {
342 $error =
'Failed to set cache for usecachekey='.$usecachekey.
' result='.$ressetcache;
347 if (empty($conf->global->MAIN_FORCELANGDIR)) {
359 $langofdir = strtolower($langarray[0]).
'_'.strtoupper($langarray[0]);
360 if ($langofdir ==
'el_EL') {
361 $langofdir =
'el_GR';
363 if ($langofdir ==
'ar_AR') {
364 $langofdir =
'ar_SA';
366 $this->
load($domain, $alt + 1, $stopafterdirection, $langofdir);
373 $langofdir =
'en_US';
374 $this->
load($domain, $alt + 1, $stopafterdirection, $langofdir);
380 $this->_tab_loaded[$newdomain] = 1;
383 if (empty($this->_tab_loaded[$newdomain])) {
384 $this->_tab_loaded[$newdomain] = 2;
390 if (empty($loadfromfileonly)) {
391 $overwritekey =
'MAIN_OVERWRITE_TRANS_'.$this->defaultlang;
392 if (!empty($conf->global->$overwritekey)) {
394 $tmparray = explode(
',', $conf->global->$overwritekey);
395 foreach ($tmparray as $tmp) {
396 $tmparray2 = explode(
':', $tmp);
397 if (!empty($tmparray2[1])) {
398 $this->tab_translate[$tmparray2[0]] = $tmparray2[1];
405 if (!empty($this->tab_translate[
"SeparatorDecimal"]) && !empty($this->tab_translate[
"SeparatorThousand"])
406 && $this->tab_translate[
"SeparatorDecimal"] == $this->tab_translate[
"SeparatorThousand"]) {
407 $this->tab_translate[
"SeparatorThousand"] =
'';
429 $domain =
'database';
438 $newdomain = $domain;
441 if (!empty($this->_tab_loaded[$newdomain])) {
446 $this->_tab_loaded[$newdomain] = 1;
449 $langofdir = $this->defaultlang;
451 if (empty($langofdir)) {
452 dol_syslog(
"Error: ".get_class($this).
"::loadFromDatabase was called but language was not set yet with langs->setDefaultLang(). Nothing will be loaded.", LOG_WARNING);
462 if (!empty($conf->memcached->enabled) && !empty($conf->global->MEMCACHED_SERVER)) {
463 $usecachekey = $newdomain.
'_'.$langofdir;
464 } elseif (isset($conf->global->MAIN_OPTIMIZE_SPEED) && ($conf->global->MAIN_OPTIMIZE_SPEED & 0x02)) {
466 $usecachekey = $newdomain;
473 require_once DOL_DOCUMENT_ROOT.
'/core/lib/memory.lib.php';
475 if (is_array($tmparray) && count($tmparray)) {
476 $this->tab_translate += $tmparray;
484 if (!$found && !empty($conf->global->MAIN_ENABLE_OVERWRITE_TRANSLATION)) {
486 $sql =
"SELECT transkey, transvalue FROM ".$db->prefix().
"overwrite_trans where lang='".$db->escape($this->defaultlang).
"' OR lang IS NULL";
487 $sql .=
" AND entity IN (0, ".getEntity(
'overwrite_trans').
")";
488 $sql .= $db->order(
"lang",
"DESC");
489 $resql = $db->query(
$sql);
492 $num = $db->num_rows($resql);
495 $tabtranslatedomain = array();
500 $obj = $db->fetch_object($resql);
502 $key = $obj->transkey;
503 $value = $obj->transvalue;
506 if (empty($this->tab_translate[$key])) {
508 $this->tab_translate[$key] = str_replace(array(
'\\n',
'\\\\s'), array(
"\n",
'\s'), $value);
511 $tabtranslatedomain[$key] = $value;
522 if ($usecachekey && count($tabtranslatedomain)) {
523 $ressetcache =
dol_setcache($usecachekey, $tabtranslatedomain);
524 if ($ressetcache < 0) {
525 $error =
'Failed to set cache for usecachekey='.$usecachekey.
' result='.$ressetcache;
536 $this->_tab_loaded[$newdomain] = 1;
539 if (empty($this->_tab_loaded[$newdomain])) {
540 $this->_tab_loaded[$newdomain] = 2;
554 return $this->_tab_loaded[$domain];
572 if (!is_string($key)) {
574 return 'ErrorBadValueForParamNotAString';
579 if (preg_match(
'/^Civility([0-9A-Z]+)$/i', $key, $reg)) {
580 $newstr = $this->
getLabelFromKey($db, $reg[1],
'c_civility',
'code',
'label');
581 } elseif (preg_match(
'/^Currency([A-Z][A-Z][A-Z])$/i', $key, $reg)) {
582 $newstr = $this->
getLabelFromKey($db, $reg[1],
'c_currencies',
'code_iso',
'label');
583 } elseif (preg_match(
'/^SendingMethod([0-9A-Z]+)$/i', $key, $reg)) {
584 $newstr = $this->
getLabelFromKey($db, $reg[1],
'c_shipment_mode',
'code',
'libelle');
585 } elseif (preg_match(
'/^PaymentType(?:Short)?([0-9A-Z]+)$/i', $key, $reg)) {
586 $newstr = $this->
getLabelFromKey($db, $reg[1],
'c_paiement',
'code',
'libelle',
'', 1);
587 } elseif (preg_match(
'/^OppStatus([0-9A-Z]+)$/i', $key, $reg)) {
588 $newstr = $this->
getLabelFromKey($db, $reg[1],
'c_lead_status',
'code',
'label');
589 } elseif (preg_match(
'/^OrderSource([0-9A-Z]+)$/i', $key, $reg)) {
617 public function trans($key, $param1 =
'', $param2 =
'', $param3 =
'', $param4 =
'', $maxsize = 0)
621 if (!empty($this->tab_translate[$key])) {
622 $str = $this->tab_translate[$key];
625 $replacekey =
'MAIN_REPLACE_TRANS_'.$this->defaultlang;
626 if (!empty($conf->global->$replacekey)) {
627 $tmparray = explode(
';', $conf->global->$replacekey);
628 foreach ($tmparray as $tmp) {
629 $tmparray2 = explode(
':', $tmp);
630 $str = preg_replace(
'/'.preg_quote($tmparray2[0]).
'/', $tmparray2[1], $str);
637 array(
'"',
'<b>',
'</b>',
'<u>',
'</u>',
'<i',
'</i>',
'<center>',
'</center>',
'<strong>',
'</strong>',
'<a ',
'</a>',
'<br>',
'<span',
'</span>',
'< ',
'>'),
638 array(
'__quot__',
'__tagb__',
'__tagbend__',
'__tagu__',
'__taguend__',
'__tagi__',
'__tagiend__',
'__tagcenter__',
'__tagcenterend__',
'__tagb__',
'__tagbend__',
'__taga__',
'__tagaend__',
'__tagbr__',
'__tagspan__',
'__tagspanend__',
'__ltspace__',
'__gt__'),
642 if (strpos($key,
'Format') !== 0) {
644 $str = sprintf($str, $param1, $param2, $param3, $param4);
651 $str = htmlentities($str, ENT_COMPAT, $this->charset_output);
655 array(
'__quot__',
'__tagb__',
'__tagbend__',
'__tagu__',
'__taguend__',
'__tagi__',
'__tagiend__',
'__tagcenter__',
'__tagcenterend__',
'__taga__',
'__tagaend__',
'__tagbr__',
'__tagspan__',
'__tagspanend__',
'__ltspace__',
'__gt__'),
656 array(
'"',
'<b>',
'</b>',
'<u>',
'</u>',
'<i',
'</i>',
'<center>',
'</center>',
'<a ',
'</a>',
'<br>',
'<span',
'</span>',
'< ',
'>'),
686 public function transnoentities($key, $param1 =
'', $param2 =
'', $param3 =
'', $param4 =
'', $param5 =
'')
711 if (!empty($this->tab_translate[$key])) {
712 $str = $this->tab_translate[$key];
715 $replacekey =
'MAIN_REPLACE_TRANS_'.$this->defaultlang;
716 if (!empty($conf->global->$replacekey)) {
717 $tmparray = explode(
';', $conf->global->$replacekey);
718 foreach ($tmparray as $tmp) {
719 $tmparray2 = explode(
':', $tmp);
720 $str = preg_replace(
'/'.preg_quote($tmparray2[0]).
'/', $tmparray2[1], $str);
724 if (!preg_match(
'/^Format/', $key)) {
726 $str = sprintf($str, $param1, $param2, $param3, $param4, $param5);
749 if (!empty($this->tab_translate[
"$str$countrycode"])) {
750 return $this->
trans(
"$str$countrycode");
752 return $this->
trans($str);
767 if (!empty($this->tab_translate[
"$str$countrycode"])) {
784 if ($pagecodefrom ==
'ISO-8859-1' && $this->charset_output ==
'UTF-8') {
785 $str = utf8_encode($str);
787 if ($pagecodefrom ==
'UTF-8' && $this->charset_output ==
'ISO-8859-1') {
788 $str = utf8_decode(str_replace(
'€', chr(128), $str));
809 $this->
load(
"languages");
812 $handle = opendir($langdir.
"/langs");
813 $langs_available = array();
814 while ($dir = trim(readdir($handle))) {
816 if (preg_match(
'/^([a-z]+)_([A-Z]+)/i', $dir, $regs)) {
819 $arrayofspecialmainlanguages = array(
848 if (strtolower($regs[1]) != strtolower($regs[2]) && !in_array($dir, $arrayofspecialmainlanguages)) {
853 if (!empty($conf->global->MAIN_LANGUAGES_ALLOWED) && !in_array($dir, explode(
',', $conf->global->MAIN_LANGUAGES_ALLOWED))) {
858 $langs_available[$dir] = $dir;
861 if ($usecode == 1 || !empty($conf->global->MAIN_SHOW_LANGUAGE_CODE)) {
862 $langs_available[$dir] = $dir.
': '.
dol_trunc($this->
trans(
'Language_'.$dir), $maxlength);
864 $langs_available[$dir] = $this->
trans(
'Language_'.$dir);
867 $langs_available[$dir] = str_replace(
' (United States)',
'', $langs_available[$dir]);
871 return $langs_available;
887 foreach ($this->dir as $searchdir) {
888 if (is_readable(
dol_osencode($searchdir.
"/langs/".$this->defaultlang.
"/".$filename))) {
894 if ($this->defaultlang !=
"en_US") {
895 $filenamealt = $searchdir.
"/langs/en_US/".$filename;
923 $newnumber = $number;
925 $dirsubstitutions = array_merge(array(), $conf->modules_parts[
'substitutions']);
926 foreach ($dirsubstitutions as $reldir) {
931 if (!is_dir($newdir)) {
935 $fonc =
'numberwords';
936 if (
file_exists($newdir.
'/functions_'.$fonc.
'.lib.php')) {
937 include_once $newdir.
'/functions_'.$fonc.
'.lib.php';
938 if (function_exists(
'numberwords_getLabelFromNumber')) {
939 $newnumber = numberwords_getLabelFromNumber($this, $number, $isamount);
964 public function getLabelFromKey($db, $key, $tablename, $fieldkey, $fieldlabel, $keyforselect =
'', $filteronentity = 0)
971 if (preg_match(
'/[^0-9A-Z_]/i', $tablename) || preg_match(
'/[^0-9A-Z_]/i', $fieldkey) || preg_match(
'/[^0-9A-Z_]/i', $fieldlabel)) {
972 $this->error =
'Bad value for parameter tablename, fieldkey or fieldlabel';
980 if ($tmp != $key && $tmp !=
'ErrorBadValueForParamNotAString') {
985 if (isset($this->cache_labels[$tablename][$key])) {
986 return $this->cache_labels[$tablename][$key];
990 $sql =
"SELECT ".$fieldlabel.
" as label";
991 $sql .=
" FROM ".$db->prefix().$tablename;
992 $sql .=
" WHERE ".$fieldkey.
" = '".$db->escape($keyforselect ? $keyforselect : $key).
"'";
993 if ($filteronentity) {
994 $sql .=
" AND entity IN (".getEntity($tablename).
')';
996 dol_syslog(get_class($this).
'::getLabelFromKey', LOG_DEBUG);
997 $resql = $db->query(
$sql);
999 $obj = $db->fetch_object($resql);
1001 $this->cache_labels[$tablename][$key] = $obj->label;
1003 $this->cache_labels[$tablename][$key] = $key;
1007 return $this->cache_labels[$tablename][$key];
1009 $this->error = $db->lasterror();
1028 if (in_array($currency_code, array(
'USD'))) {
1029 return $symbol.$amount;
1031 return $amount.$symbol;
1045 $currency_sign =
'';
1047 if (function_exists(
"mb_convert_encoding")) {
1050 if (isset($this->cache_currencies[$currency_code]) && !empty($this->cache_currencies[$currency_code][
'unicode']) && is_array($this->cache_currencies[$currency_code][
'unicode'])) {
1051 foreach ($this->cache_currencies[$currency_code][
'unicode'] as $unicode) {
1052 $currency_sign .= mb_convert_encoding(
"&#{$unicode};",
"UTF-8",
'HTML-ENTITIES');
1057 return ($currency_sign ? $currency_sign : $currency_code);
1070 if ($this->cache_currencies_all_loaded) {
1073 if (!empty($currency_code) && isset($this->cache_currencies[$currency_code])) {
1077 $sql =
"SELECT code_iso, label, unicode";
1078 $sql .=
" FROM ".$db->prefix().
"c_currencies";
1079 $sql .=
" WHERE active = 1";
1080 if (!empty($currency_code)) {
1081 $sql .=
" AND code_iso = '".$db->escape($currency_code).
"'";
1085 dol_syslog(get_class($this).
'::loadCacheCurrencies', LOG_DEBUG);
1086 $resql = $db->query(
$sql);
1088 $this->
load(
"dict");
1090 if (!empty($currency_code)) {
1091 foreach ($this->cache_currencies as $key => $val) {
1092 $label[$key] = $val[
'label'];
1096 $num = $db->num_rows($resql);
1099 $obj = $db->fetch_object($resql);
1102 $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 :
''));
1103 $this->cache_currencies[$obj->code_iso][
'unicode'] = (array) json_decode((empty($obj->unicode) ?
'' : $obj->unicode),
true);
1104 $label[$obj->code_iso] = $this->cache_currencies[$obj->code_iso][
'label'];
1108 if (empty($currency_code)) {
1109 $this->cache_currencies_all_loaded =
true;
1114 array_multisort($label, SORT_ASC, $this->cache_currencies);
1133 $substitutionarray = array();
1135 foreach ($this->tab_translate as $code => $label) {
1136 $substitutionarray[
'lang_'.$code] = $label;
1137 $substitutionarray[
'__('.$code.
')__'] = $label;
1140 return $substitutionarray;