/** * Get the human-readable form of a language id, or a language entry from a language INI file. (STUB) * * @param ID_TEXT The language id * @param ?mixed The first token [string or tempcode] (replaces {1}) (NULL: none) * @param ?mixed The second token [string or tempcode] (replaces {2}) (NULL: none) * @param ?mixed The third token (replaces {3}). May be an array of [of string], to allow any number of additional args (NULL: none) * @param ?LANGUAGE_NAME The language to use (NULL: users language) * @param boolean Whether to cause ocPortal to exit if the lookup does not succeed * @return ?mixed The human-readable content (NULL: not found). String normally. Tempcode if tempcode parameters. */ function do_lang($a, $param_a = NULL, $param_b = NULL, $param_c = NULL, $lang = NULL, $require_result = true) { if (function_exists('_do_lang')) { return _do_lang($a, $param_a, $param_b, $param_c, $lang, $require_result); } switch ($a) { case 'LINK_NEW_WINDOW': return 'new window'; case 'SPREAD_TABLE': return 'Spread table'; case 'MAP_TABLE': return 'Item to value mapper table'; case 'charset': return NULL; } if (is_null($param_a)) { return $a; } return serialize(array($a, $param_a, $param_b, $param_c)); }
/** * Get the human-readable form of a language id, or a language entry from a language INI file. * * @param ID_TEXT The language id * @param ?mixed The first token [string or tempcode] (replaces {1}) (NULL: none) * @param ?mixed The second token [string or tempcode] (replaces {2}) (NULL: none) * @param ?mixed The third token (replaces {3}). May be an array of [of string], to allow any number of additional args (NULL: none) * @param ?LANGUAGE_NAME The language to use (NULL: users language) * @param boolean Whether to cause ocPortal to exit if the lookup does not succeed * @return ?mixed The human-readable content (NULL: not found). String normally. Tempcode if tempcode parameters. */ function _do_lang($codename, $token1 = NULL, $token2 = NULL, $token3 = NULL, $lang = NULL, $require_result = true) { $pos = strpos($codename, ':'); if ($pos !== false) { require_lang(substr($codename, 0, $pos)); $codename = substr($codename, $pos + 1); } global $LANGUAGE, $USER_LANG_CACHED, $RECORD_LANG_STRINGS, $XSS_DETECT, $PAGE_CACHE_FILE, $PAGE_CACHE_LANG_LOADED; if ($RECORD_LANG_STRINGS) { global $RECORDED_LANG_STRINGS; $RECORDED_LANG_STRINGS[$codename] = 1; } if ($lang === NULL) { $lang = $USER_LANG_CACHED === NULL ? user_lang() : $USER_LANG_CACHED; } if (!isset($LANGUAGE[$lang][$codename]) && (!array_key_exists($lang, $LANGUAGE) || !array_key_exists($codename, $LANGUAGE[$lang]))) { global $PAGE_CACHE_LAZY_LOAD, $PAGE_CACHE_LANGS_REQUESTED, $LANG_REQUESTED_LANG; if ($PAGE_CACHE_LAZY_LOAD) { $PAGE_CACHE_LAZY_LOAD = false; // We can't be lazy any more, but we will keep growing our pool so hopefully CAN be lazy the next time foreach ($PAGE_CACHE_LANGS_REQUESTED as $request) { list($that_codename, $that_lang) = $request; unset($LANG_REQUESTED_LANG[$that_lang][$that_codename]); require_lang($that_codename, $that_lang, NULL, true); } $ret = _do_lang($codename, $token1, $token2, $token3, $lang, $require_result); if ($ret === NULL) { $PAGE_CACHE_LANG_LOADED[$lang][$codename] = NULL; if ($GLOBALS['MEM_CACHE'] !== NULL) { persistant_cache_set($PAGE_CACHE_FILE, $PAGE_CACHE_LANG_LOADED); } else { @rewind($PAGE_CACHE_FILE); @ftruncate($PAGE_CACHE_FILE, 0); @fwrite($PAGE_CACHE_FILE, serialize($PAGE_CACHE_LANG_LOADED)); } } return $ret; } require_all_open_lang_files($lang); } if ($lang == 'xxx') { return 'xxx'; } // Helpful for testing language compliancy. We don't expect to see non x's if we're running this language if (!isset($LANGUAGE[$lang][$codename]) && (!array_key_exists($lang, $LANGUAGE) || !array_key_exists($codename, $LANGUAGE[$lang]))) { if ($lang != fallback_lang()) { $ret = do_lang($codename, $token1, $token2, $token3, fallback_lang(), $require_result); if ($codename == 'charset') { switch (strtolower($lang)) { case 'ar': case 'bg': case 'zh-CN': case 'zh-TW': case 'hr': case 'cs': case 'da': case 'nl': case 'fi': case 'fr': case 'de': case 'el': case 'hi': case 'it': case 'ja': case 'ko': case 'pl': case 'pt': case 'ro': case 'ru': case 'es': case 'sv': $ret = 'utf-8'; break; } } elseif (substr($codename, 0, 3) == 'FC_') { $ret = ocp_mb_substr(trim(do_lang(substr($codename, 3), $token1, $token2, $token3, $lang)), 0, 1); } elseif ($codename == 'locale') { $ret = strtolower($lang) . '_' . strtoupper($lang); } else { $ret2 = strtolower($codename) != $codename ? google_translate($ret, $lang) : $ret; if ($ret2 != $ret) { $ret = $ret2; } } if ($PAGE_CACHE_FILE !== NULL) { if (!isset($PAGE_CACHE_LANG_LOADED[$lang][$codename]) && isset($PAGE_CACHE_LANG_LOADED[fallback_lang()][$codename])) { $PAGE_CACHE_LANG_LOADED[$lang][$codename] = $ret; // Will have been cached into fallback_lang() from the nested do_lang call, we need to copy it into our cache bucket for this language if ($GLOBALS['MEM_CACHE'] !== NULL) { persistant_cache_set($PAGE_CACHE_FILE, $PAGE_CACHE_LANG_LOADED); } else { @rewind($PAGE_CACHE_FILE); @ftruncate($PAGE_CACHE_FILE, 0); @fwrite($PAGE_CACHE_FILE, serialize($PAGE_CACHE_LANG_LOADED)); } } } return $ret; } else { if ($require_result) { global $USER_LANG_LOOP, $REQUIRE_LANG_LOOP; //print_r(debug_backtrace()); if ($USER_LANG_LOOP == 1) { critical_error('RELAY', 'Missing language code: ' . escape_html($codename) . '. This language code is required to produce error messages, and thus a critical error was prompted by the non-ability to show less-critical error messages. It is likely the source language files (lang/' . fallback_lang() . '/*.ini) for ocPortal on this website have been corrupted.'); } if ($REQUIRE_LANG_LOOP >= 2) { return ''; } // Probably failing to load global.ini, so just output with some text missing require_code('view_modes'); erase_cached_language(); fatal_exit(do_lang_tempcode('MISSING_LANG_ENTRY', escape_html($codename))); } else { return NULL; } } } if ($PAGE_CACHE_FILE !== NULL) { if (!isset($PAGE_CACHE_LANG_LOADED[$lang][$codename])) { $PAGE_CACHE_LANG_LOADED[$lang][$codename] = $LANGUAGE[$lang][$codename]; if ($GLOBALS['MEM_CACHE'] !== NULL) { persistant_cache_set($PAGE_CACHE_FILE, $PAGE_CACHE_LANG_LOADED); } else { @rewind($PAGE_CACHE_FILE); @ftruncate($PAGE_CACHE_FILE, 0); @fwrite($PAGE_CACHE_FILE, serialize($PAGE_CACHE_LANG_LOADED)); } } } // Put in parameters static $non_plural_non_vowel = array('1', 'b', 'c', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'm', 'n', 'p', 'q', 'r', 's', 't', 'v', 'w', 'x', 'y', 'z'); $looked_up = $LANGUAGE[$lang][$codename]; if ($looked_up === NULL) { return NULL; } // Learning cache pool has told us this string definitely does not exist $out = str_replace('\\n', "\n", $looked_up); $plural_or_vowel_check = strpos($out, '|') !== false; if ($XSS_DETECT) { ocp_mark_as_escaped($out); } if ($token1 !== NULL) { if (is_object($token1) && $token2 === NULL || $token2 !== NULL && is_object($token2)) { $bits = preg_split('#\\{\\d[^\\}]*\\}#', $out, 2, PREG_SPLIT_OFFSET_CAPTURE); $ret = new ocp_tempcode(); foreach ($bits as $bit) { if ($XSS_DETECT) { ocp_mark_as_escaped($bit[0]); } $at = $bit[1]; if ($at != 0) { if ($out[$at - 2] == '1') { $ret->attach($token1); } elseif ($out[$at - 2] == '2') { $ret->attach($token2); } elseif ($plural_or_vowel_check && substr($out[$at - 2], 0, 2) == '1|') { $exploded = explode('|', $out[$at - 2]); $_token = $token1->evaluate(); $_token_denum = str_replace(',', '', $_token); $ret->attach(in_array(is_numeric($_token_denum) ? $_token_denum : strtolower(substr($_token, 0, 1)), $non_plural_non_vowel) ? $exploded[1] : $exploded[2]); } elseif ($plural_or_vowel_check && substr($out[$at - 2], 0, 2) == '2|') { $exploded = explode('|', $out[$at - 2]); $_token = $token2->evaluate(); $_token_denum = str_replace(',', '', $_token); $ret->attach(in_array(is_numeric($_token_denum) ? $_token_denum : strtolower(substr($_token, 0, 1)), $non_plural_non_vowel) ? $exploded[1] : $exploded[2]); } } $ret->attach($bit[0]); } return $ret; } elseif ($token1 !== NULL) { $out = str_replace('{1}', $token1, $out); if ($plural_or_vowel_check) { $_token_denum = str_replace(',', '', $token1); $out = preg_replace('#\\{1\\|(.*)\\|(.*)\\}#U', in_array(is_numeric($_token_denum) ? $_token_denum : strtolower(substr($token1, 0, 1)), $non_plural_non_vowel) ? '\\1' : '\\2', $out); } if ($XSS_DETECT && ocp_is_escaped($token1)) { ocp_mark_as_escaped($out); } } if ($token2 !== NULL) { if ($XSS_DETECT) { $escaped = ocp_is_escaped($out); } $out = str_replace('{2}', $token2, $out); if ($plural_or_vowel_check) { $_token_denum = str_replace(',', '', $token1); $out = preg_replace('#\\{2\\|(.*)\\|(.*)\\}#U', in_array(is_numeric($_token_denum) ? $_token_denum : strtolower(substr($token2, 0, 1)), $non_plural_non_vowel) ? '\\1' : '\\2', $out); } if ($XSS_DETECT && ocp_is_escaped($token2) && $escaped) { ocp_mark_as_escaped($out); } if ($token3 !== NULL) { $i = 3; if (!is_array($token3)) { $token3 = array($token3); } foreach ($token3 as $token) { if ($XSS_DETECT) { $escaped = ocp_is_escaped($out); } $out = str_replace('{' . strval($i) . '}', $token, $out); if ($plural_or_vowel_check) { $_token_denum = str_replace(',', '', $token); $out = preg_replace('#\\{' . strval($i) . '\\|(.*)\\|(.*)\\}#U', in_array(is_numeric($_token_denum) ? $_token_denum : strtolower(substr($token, 0, 1)), $non_plural_non_vowel) ? '\\1' : '\\2', $out); } if ($XSS_DETECT && ocp_is_escaped($token) && $escaped) { ocp_mark_as_escaped($out); } $i++; } } } } return $out; }
/** * Get the human-readable form of a language id, or a language entry from a language INI file. (STUB) * * @param ID_TEXT The language id * @param ?mixed The first token [string or tempcode] (replaces {1}) (NULL: none) * @param ?mixed The second token [string or tempcode] (replaces {2}) (NULL: none) * @param ?mixed The third token (replaces {3}). May be an array of [of string], to allow any number of additional args (NULL: none) * @param ?LANGUAGE_NAME The language to use (NULL: users language) * @param boolean Whether to cause ocPortal to exit if the lookup does not succeed * @return ?mixed The human-readable content (NULL: not found). String normally. Tempcode if tempcode parameters. */ function do_lang($a, $param_a = NULL, $param_b = NULL, $param_c = NULL, $lang = NULL, $require_result = true) { if (function_exists('_do_lang')) { return _do_lang($a, $param_a, $param_b, $param_c, $lang, $require_result); } unset($lang); unset($allow_fail); switch ($a) { case 'LINK_NEW_WINDOW': return 'new window'; case 'SPREAD_TABLE': return 'Spread table'; case 'MAP_TABLE': return 'Item to value mapper table'; } return array($a, $param_a, $param_b, $param_c); }
/** * Get the human-readable form of a language id, or a language entry from a language INI file. * * @param ID_TEXT The language id * @param ?mixed The first token [string or tempcode] (replaces {1}) (NULL: none) * @param ?mixed The second token [string or tempcode] (replaces {2}) (NULL: none) * @param ?mixed The third token (replaces {3}). May be an array of [of string], to allow any number of additional args (NULL: none) * @param ?LANGUAGE_NAME The language to use (NULL: users language) * @param boolean Whether to cause ocPortal to exit if the lookup does not succeed * @return ?mixed The human-readable content (NULL: not found). String normally. Tempcode if tempcode parameters. */ function _do_lang($codename, $token1 = NULL, $token2 = NULL, $token3 = NULL, $lang = NULL, $require_result = true) { global $LANGUAGE, $USER_LANG_CACHED, $RECORD_LANG_STRINGS, $XSS_DETECT, $PAGE_CACHE_FILE, $PAGE_CACHE_LANG_LOADED; if ($lang === NULL) { $lang = $USER_LANG_CACHED === NULL ? user_lang() : $USER_LANG_CACHED; } if ($GLOBALS['SEMI_DEBUG_MODE']) { $pos = strpos($codename, '='); if ($pos !== false) { // Find loaded file with smallest levenstein distance to current page $best = mixed(); $best_for = NULL; global $LANGS_REQUESTED; foreach (array_keys($LANGS_REQUESTED) as $possible) { $dist = levenshtein(get_page_name(), $possible); if (is_null($best) || $best > $dist) { $best = $dist; $best_for = $possible; } } $save_path = get_file_base() . '/lang/' . fallback_lang() . '/' . $best_for . '.ini'; if (!is_file($save_path)) { $save_path = get_file_base() . '/lang_custom/' . fallback_lang() . '/' . $best_for . '.ini'; } // Tack language strings onto this file list($codename, $value) = explode('=', $codename, 2); $myfile = fopen($save_path, 'at'); fwrite($myfile, "\n" . $codename . '=' . $value); fclose($myfile); // Fake-load the string $LANGUAGE[$lang][$codename] = $value; // Go through all required files, doing a string replace if needed $included_files = get_included_files(); foreach ($included_files as $inc) { $orig_contents = file_get_contents($inc); $contents = str_replace("'" . $codename . '=' . $value . "'", "'" . $codename . "'", $orig_contents); if ($orig_contents != $contents) { $myfile = fopen($inc, 'wt'); fwrite($myfile, $contents); fclose($myfile); } } } } $there = isset($LANGUAGE[$lang][$codename]); if (!$there) { $pos = strpos($codename, ':'); if ($pos !== false) { require_lang(substr($codename, 0, $pos), NULL, NULL, !$require_result); $codename = substr($codename, $pos + 1); } $there = isset($LANGUAGE[$lang][$codename]); } if ($RECORD_LANG_STRINGS) { global $RECORDED_LANG_STRINGS; $RECORDED_LANG_STRINGS[$codename] = 1; } if (!$there && (!isset($LANGUAGE[$lang]) || !array_key_exists($codename, $LANGUAGE[$lang]))) { global $PAGE_CACHE_LAZY_LOAD, $PAGE_CACHE_LANGS_REQUESTED, $LANG_REQUESTED_LANG; if ($PAGE_CACHE_LAZY_LOAD) { $PAGE_CACHE_LAZY_LOAD = false; // We can't be lazy any more, but we will keep growing our pool so hopefully CAN be lazy the next time foreach ($PAGE_CACHE_LANGS_REQUESTED as $request) { list($that_codename, $that_lang) = $request; unset($LANG_REQUESTED_LANG[$that_lang][$that_codename]); require_lang($that_codename, $that_lang, NULL, true); } $ret = _do_lang($codename, $token1, $token2, $token3, $lang, $require_result); if ($ret === NULL) { $PAGE_CACHE_LANG_LOADED[$lang][$codename] = NULL; if ($GLOBALS['MEM_CACHE'] !== NULL) { persistant_cache_set($PAGE_CACHE_FILE, $PAGE_CACHE_LANG_LOADED); } else { open_page_cache_file(); @rewind($PAGE_CACHE_FILE); @flock($PAGE_CACHE_FILE, LOCK_EX); @ftruncate($PAGE_CACHE_FILE, 0); @fwrite($PAGE_CACHE_FILE, serialize($PAGE_CACHE_LANG_LOADED)); @flock($PAGE_CACHE_FILE, LOCK_UN); } } return $ret; } require_all_open_lang_files($lang); } if ($lang == 'xxx') { return 'xxx'; } // Helpful for testing language compliancy. We don't expect to see non x's if we're running this language if (!isset($LANGUAGE[$lang][$codename]) && ($require_result || !isset($LANGUAGE[$lang]) || !array_key_exists($codename, $LANGUAGE[$lang]))) { if ($lang != fallback_lang()) { $ret = do_lang($codename, $token1, $token2, $token3, fallback_lang(), $require_result); if ($PAGE_CACHE_FILE !== NULL) { if (!isset($PAGE_CACHE_LANG_LOADED[$lang][$codename]) && isset($PAGE_CACHE_LANG_LOADED[fallback_lang()][$codename])) { $PAGE_CACHE_LANG_LOADED[$lang][$codename] = $PAGE_CACHE_LANG_LOADED[fallback_lang()][$codename]; // Will have been cached into fallback_lang() from the nested do_lang call, we need to copy it into our cache bucket for this language if ($GLOBALS['MEM_CACHE'] !== NULL) { persistant_cache_set($PAGE_CACHE_FILE, $PAGE_CACHE_LANG_LOADED); } else { open_page_cache_file(); @rewind($PAGE_CACHE_FILE); @flock($PAGE_CACHE_FILE, LOCK_EX); @ftruncate($PAGE_CACHE_FILE, 0); @fwrite($PAGE_CACHE_FILE, serialize($PAGE_CACHE_LANG_LOADED)); @flock($PAGE_CACHE_FILE, LOCK_UN); } } } return $ret; } else { if ($require_result) { global $USER_LANG_LOOP, $REQUIRE_LANG_LOOP; //print_r(debug_backtrace()); if ($USER_LANG_LOOP == 1) { critical_error('RELAY', 'Missing language code: ' . escape_html($codename) . '. This language code is required to produce error messages, and thus a critical error was prompted by the non-ability to show less-critical error messages. It is likely the source language files (lang/' . fallback_lang() . '/*.ini) for ocPortal on this website have been corrupted.'); } if ($REQUIRE_LANG_LOOP >= 2) { return ''; } // Probably failing to load global.ini, so just output with some text missing require_code('view_modes'); erase_cached_language(); require_code('site'); attach_message(do_lang_tempcode('MISSING_LANG_ENTRY', escape_html($codename)), 'warn'); return ''; } else { return NULL; } } } if ($PAGE_CACHE_FILE !== NULL) { if (!isset($PAGE_CACHE_LANG_LOADED[$lang][$codename]) && (!isset($PAGE_CACHE_LANG_LOADED[$lang]) || !array_key_exists($codename, $PAGE_CACHE_LANG_LOADED[$lang]))) { $PAGE_CACHE_LANG_LOADED[$lang][$codename] = $LANGUAGE[$lang][$codename]; if ($GLOBALS['MEM_CACHE'] !== NULL) { persistant_cache_set($PAGE_CACHE_FILE, $PAGE_CACHE_LANG_LOADED); } else { open_page_cache_file(); @rewind($PAGE_CACHE_FILE); @flock($PAGE_CACHE_FILE, LOCK_EX); @ftruncate($PAGE_CACHE_FILE, 0); @fwrite($PAGE_CACHE_FILE, serialize($PAGE_CACHE_LANG_LOADED)); @flock($PAGE_CACHE_FILE, LOCK_UN); } } } // Put in parameters static $non_plural_non_vowel = array('1', 'b', 'c', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'm', 'n', 'p', 'q', 'r', 's', 't', 'v', 'w', 'x', 'y', 'z', '{'); $looked_up = $LANGUAGE[$lang][$codename]; if ($looked_up === NULL) { return NULL; // Learning cache pool has told us this string definitely does not exist } $out = str_replace('\\n', "\n", $looked_up); $plural_or_vowel_check = strpos($out, '|') !== false; if ($XSS_DETECT) { ocp_mark_as_escaped($out); } if ($token1 !== NULL) { if (is_object($token1) && $token2 === NULL || $token2 !== NULL && is_object($token2)) { $bits = preg_split('#\\{\\d[^\\}]*\\}#', $out, 2, PREG_SPLIT_OFFSET_CAPTURE); $ret = new ocp_tempcode(); foreach ($bits as $bit) { if ($XSS_DETECT) { ocp_mark_as_escaped($bit[0]); } $at = $bit[1]; if ($at != 0) { if ($out[$at - 2] == '1') { $ret->attach($token1); } elseif ($out[$at - 2] == '2') { $ret->attach($token2); } elseif ($plural_or_vowel_check && substr($out[$at - 2], 0, 2) == '1|') { $exploded = explode('|', $out[$at - 2]); $_token = $token1->evaluate(); $_token_denum = str_replace(',', '', $_token); $ret->attach(in_array(is_numeric($_token_denum) ? $_token_denum : ocp_mb_strtolower(ocp_mb_substr($_token, 0, 1)), $non_plural_non_vowel) ? $exploded[1] : $exploded[2]); } elseif ($plural_or_vowel_check && substr($out[$at - 2], 0, 2) == '2|') { $exploded = explode('|', $out[$at - 2]); $_token = $token2->evaluate(); $_token_denum = str_replace(',', '', $_token); $ret->attach(in_array(is_numeric($_token_denum) ? $_token_denum : ocp_mb_strtolower(ocp_mb_substr($_token, 0, 1)), $non_plural_non_vowel) ? $exploded[1] : $exploded[2]); } } $ret->attach($bit[0]); } return $ret; } elseif ($token1 !== NULL) { $out = str_replace('{1}', $token1, $out); if ($plural_or_vowel_check) { $_token_denum = str_replace(',', '', $token1); $out = preg_replace('#\\{1\\|(.*)\\|(.*)\\}#U', in_array(is_numeric($_token_denum) ? $_token_denum : ocp_mb_strtolower(ocp_mb_substr($token1, 0, 1)), $non_plural_non_vowel) ? '\\1' : '\\2', $out); } if ($XSS_DETECT && ocp_is_escaped($token1)) { ocp_mark_as_escaped($out); } } if ($token2 !== NULL) { if ($XSS_DETECT) { $escaped = ocp_is_escaped($out); } $out = str_replace('{2}', $token2, $out); if ($plural_or_vowel_check) { $_token_denum = str_replace(',', '', $token1); $out = preg_replace('#\\{2\\|(.*)\\|(.*)\\}#U', in_array(is_numeric($_token_denum) ? $_token_denum : ocp_mb_strtolower(ocp_mb_substr($token2, 0, 1)), $non_plural_non_vowel) ? '\\1' : '\\2', $out); } if ($XSS_DETECT && ocp_is_escaped($token2) && $escaped) { ocp_mark_as_escaped($out); } if ($token3 !== NULL) { $i = 3; if (!is_array($token3)) { $token3 = array($token3); } foreach ($token3 as $token) { if ($XSS_DETECT) { $escaped = ocp_is_escaped($out); } $out = str_replace('{' . strval($i) . '}', $token, $out); if ($plural_or_vowel_check) { $_token_denum = str_replace(',', '', $token); $out = preg_replace('#\\{' . strval($i) . '\\|(.*)\\|(.*)\\}#U', in_array(is_numeric($_token_denum) ? $_token_denum : ocp_mb_strtolower(ocp_mb_substr($token, 0, 1)), $non_plural_non_vowel) ? '\\1' : '\\2', $out); } if ($XSS_DETECT && ocp_is_escaped($token) && $escaped) { ocp_mark_as_escaped($out); } $i++; } } } } return $out; }