/** * Get localized time units for a particular language, using fallback languages for missing * items. The time units are returned as an associative array. The keys are of the form: * <unit>-<tense>-<ordinality> (for example, 'hour-future-two'). The values include a placeholder * for the number (for example, '{0} months ago'). * * @param string $code The language to return the list in * @return array an associative array of time unit codes and localized time units */ public static function getUnits($code) { // Load time units localized for the requested language $units = self::loadLanguage($code); if ($units) { return $units; } // Load missing time units from fallback languages if (is_callable(array('Language', 'getFallbacksFor'))) { // MediaWiki 1.19 $fallbacks = Language::getFallbacksFor($code); foreach ($fallbacks as $fallback) { if ($units) { break; } // Get time units from a fallback language $units = self::loadLanguage($fallback); } } else { // MediaWiki 1.18 or earlier $fallback = $code; while ($fallback = Language::getFallbackFor($fallback)) { if ($units) { break; } // Get time units from a fallback language $units = self::loadLanguage($fallback); } } return $units; }
/** * Internal utility function for initialising the global entity language * fallback sequence. */ function initLanguage( $user, $election ) { global $wgRequest, $wgLang; $uselang = $wgRequest->getVal( 'uselang' ); if ( $uselang !== null ) { $userLang = $uselang; } elseif ( $user instanceof SecurePoll_Voter ) { $userLang = $user->getLanguage(); } else { $userLang = $user->getOption( 'language' ); } $wgLang = Language::factory( $userLang ); $languages = array( $userLang ); $fallback = $userLang; while ( $fallback = Language::getFallbackFor( $fallback ) ) { $languages[] = $fallback; } if ( $fallback != $election->getLanguage() ) { $fallback = $election->getLanguage(); $languages[] = $fallback; } if ( $fallback != 'en' ) { $languages[] = 'en'; } $this->context->setLanguages( $languages ); }
/** * Get localized language names for a particular language, using fallback languages for missing * items. * * @param $code string * @param $fbMethod int * @param $list int * @throws Exception * @return array an associative array of language codes and localized language names */ public static function getNames($code, $fbMethod = self::FALLBACK_NATIVE, $list = self::LIST_MW) { $xx = self::loadLanguage($code); $native = Language::fetchLanguageNames(null, $list === self::LIST_MW_SUPPORTED ? 'mwfile' : 'mw'); if ($fbMethod === self::FALLBACK_NATIVE) { $names = array_merge($native, $xx); } elseif ($fbMethod === self::FALLBACK_NORMAL) { // Load missing language names from fallback languages $fb = $xx; if (is_callable(array('Language', 'getFallbacksFor'))) { // MediaWiki 1.19 $fallbacks = Language::getFallbacksFor($code); foreach ($fallbacks as $fallback) { // Overwrite the things in fallback with what we have already $fb = array_merge(self::loadLanguage($fallback), $fb); } } else { // MediaWiki 1.18 or earlier $fallback = $code; while ($fallback = Language::getFallbackFor($fallback)) { // Overwrite the things in fallback with what we have already $fb = array_merge(self::loadLanguage($fallback), $fb); } } /* Add native names for codes that are not in cldr */ $names = array_merge($native, $fb); /* As a last resort, try the native name in Names.php */ if (!isset($names[$code]) && isset($native[$code])) { $names[$code] = $native[$code]; } } else { throw new Exception("Invalid value for 2:\$fallback in " . __METHOD__); } switch ($list) { case self::LIST_MW: case self::LIST_MW_SUPPORTED: /* Remove entries that are not in fb */ $names = array_intersect_key($names, $native); /* And fall to the return */ /* And fall to the return */ case self::LIST_MW_AND_CLDR: return $names; default: throw new Exception("Invalid value for 3:\$list in " . __METHOD__); } }
/** * Get localized country names for a particular language, using fallback languages for missing * items. * * @param string $code The language to return the list in * @param int $fbMethod The fallback method * @return an associative array of country codes and localized country names */ public static function getNames($code) { // Load country names localized for the requested language $names = self::loadLanguage($code); // Load missing country names from fallback languages if (is_callable(array('Language', 'getFallbacksFor'))) { // MediaWiki 1.19 $fallbacks = Language::getFallbacksFor($code); foreach ($fallbacks as $fallback) { // Overwrite the things in fallback with what we have already $names = array_merge(self::loadLanguage($fallback), $names); } } else { // MediaWiki 1.18 or earlier $fallback = $code; while ($fallback = Language::getFallbackFor($fallback)) { // Overwrite the things in fallback with what we have already $names = array_merge(self::loadLanguage($fallback), $names); } } return $names; }
/** * Create a language object for a given language code * @param $code String * @return Language */ protected static function newFromCode($code) { global $IP; static $recursionLevel = 0; // Protect against path traversal below if (!Language::isValidCode($code) || strcspn($code, ":/\\") !== strlen($code)) { throw new MWException("Invalid language code \"{$code}\""); } if (!Language::isValidBuiltInCode($code)) { // It's not possible to customise this code with class files, so // just return a Language object. This is to support uselang= hacks. $lang = new Language(); $lang->setCode($code); return $lang; } if ($code == 'en') { $class = 'Language'; } else { $class = 'Language' . str_replace('-', '_', ucfirst($code)); if (!defined('MW_COMPILED')) { // Preload base classes to work around APC/PHP5 bug if (file_exists("{$IP}/languages/classes/{$class}.deps.php")) { include_once "{$IP}/languages/classes/{$class}.deps.php"; } if (file_exists("{$IP}/languages/classes/{$class}.php")) { include_once "{$IP}/languages/classes/{$class}.php"; } } } if ($recursionLevel > 5) { throw new MWException("Language fallback loop detected when creating class {$class}\n"); } if (!MWInit::classExists($class)) { $fallback = Language::getFallbackFor($code); ++$recursionLevel; $lang = Language::newFromCode($fallback); --$recursionLevel; $lang->setCode($code); } else { $lang = new $class(); } return $lang; }
/** * @param $code string * @return array */ protected static function getFallbacks($code) { global $wgUser, $wgTranslateLanguageFallbacks; // User preference has the final say $preference = $wgUser->getOption('translate-editlangs'); if ($preference !== 'default') { $fallbacks = array_map('trim', explode(',', $preference)); foreach ($fallbacks as $k => $v) { if ($v === $code) { unset($fallbacks[$k]); } } return $fallbacks; } // Global configuration settings $fallbacks = array(); if (isset($wgTranslateLanguageFallbacks[$code])) { $fallbacks = (array) $wgTranslateLanguageFallbacks[$code]; } // BC <1.19 if (method_exists('Language', 'getFallbacksFor')) { $list = Language::getFallbacksFor($code); array_pop($list); // Get 'en' away from the end $fallbacks = array_merge($list, $fallbacks); } else { $realFallback = $code ? Language::getFallbackFor($code) : false; if ($realFallback && $realFallback !== 'en') { $fallbacks = array_merge(array($realFallback), $fallbacks); } } return array_unique($fallbacks); }
/** * Create a language object for a given language code */ protected static function newFromCode($code) { global $IP; static $recursionLevel = 0; // Protect against path traversal below if (!Language::isValidCode($code) || strcspn($code, "/\\") !== strlen($code)) { throw new MWException("Invalid language code \"{$code}\""); } if ($code == 'en') { $class = 'Language'; } else { $class = 'Language' . str_replace('-', '_', ucfirst($code)); // Preload base classes to work around APC/PHP5 bug if (file_exists("{$IP}/languages/classes/{$class}.deps.php")) { include_once "{$IP}/languages/classes/{$class}.deps.php"; } if (file_exists("{$IP}/languages/classes/{$class}.php")) { include_once "{$IP}/languages/classes/{$class}.php"; } } if ($recursionLevel > 5) { throw new MWException("Language fallback loop detected when creating class {$class}\n"); } if (!class_exists($class)) { $fallback = Language::getFallbackFor($code); ++$recursionLevel; $lang = Language::newFromCode($fallback); --$recursionLevel; $lang->setCode($code); } else { $lang = new $class(); } return $lang; }
protected function stage_language($type = 'request') { $language = strtolower($this->staged_data['language']); switch ($type) { case 'request': $count = 0; //Count's just there making sure we don't get stuck here. while (!in_array($language, $this->getAvailableLanguages()) && $count < 3) { // Get the fallback language $language = Language::getFallbackFor($language); $count += 1; } if (!in_array($language, $this->getAvailableLanguages())) { $language = 'en'; } if ($language === 'zh') { //Handles GC's mutant Chinese code. $language = 'sc'; } break; case 'response': if ($language === 'sc') { $language = 'zh'; } break; } $this->staged_data['language'] = $language; }
/** * Handle local redirect * @param bool $priority Whether or not we handle this request on behalf of a priority country */ public function localRedirect($country, $language, $priority = false) { global $wgOut, $wgRequest; $landingPage = $wgRequest->getVal('landing_page', 'Donate'); /** * Construct new query string for tracking * * Note that both 'language' and 'uselang' get set to * $wgRequest->getVal( 'language', 'en') * This is wacky, yet by design! This is a unique oddity to fundraising * stuff, but CentralNotice converts wgUserLanguage to 'language' rather than * 'uselang'. Ultimately, this is something that should probably be rectified * in CentralNotice. Until then, this is what we've got. */ $tracking = wfArrayToCGI(array('utm_source' => $wgRequest->getVal('utm_source'), 'utm_medium' => $wgRequest->getVal('utm_medium'), 'utm_campaign' => $wgRequest->getVal('utm_campaign'), 'language' => $wgRequest->getVal('language', 'en'), 'uselang' => $wgRequest->getVal('language', 'en'), 'country' => $country, 'referrer' => $wgRequest->getHeader('referer'))); if ($priority) { // Build array of landing pages to check for $targetTexts = array($landingPage . '/' . $country . '/' . $language, $landingPage . '/' . $country); } else { // Build array of landing pages to check for $targetTexts = array($landingPage . '/' . $language . '/' . $country, $landingPage . '/' . $language); // Add fallback languages $code = $language; while ($code !== 'en') { $code = Language::getFallbackFor($code); $targetTexts[] = $landingPage . '/' . $code; } } // Go through the possible landing pages and redirect the user as soon as one is found to exist foreach ($targetTexts as $targetText) { $target = Title::newFromText($targetText); if ($target && $target->isKnown() && $target->getNamespace() == NS_MAIN) { if ($this->basic) { $wgOut->redirect($target->getLocalURL()); } else { $wgOut->redirect($target->getLocalURL($tracking)); } return; } } # Output a simple error message if no pages were found $this->setHeaders(); $this->outputHeader(); $wgOut->addWikiMsg('landingcheck-nopage'); }
/** * Create a language object for a given language code */ static function factory($code) { global $IP; static $recursionLevel = 0; if ($code == 'en') { $class = 'Language'; } else { $class = 'Language' . str_replace('-', '_', ucfirst($code)); // Preload base classes to work around APC/PHP5 bug if (file_exists("{$IP}/languages/classes/{$class}.deps.php")) { include_once "{$IP}/languages/classes/{$class}.deps.php"; } if (file_exists("{$IP}/languages/classes/{$class}.php")) { include_once "{$IP}/languages/classes/{$class}.php"; } } if ($recursionLevel > 5) { throw new MWException("Language fallback loop detected when creating class {$class}\n"); } if (!class_exists($class)) { $fallback = Language::getFallbackFor($code); ++$recursionLevel; $lang = Language::factory($fallback); --$recursionLevel; $lang->setCode($code); } else { $lang = new $class(); } return $lang; }