* * @throws LanguageNotFoundException */ public static function getLanguageList(string $path = "") : array{ if($path === ""){ $path = \pocketmine\RESOURCE_PATH . "locale/"; } if(is_dir($path)){ $allFiles = scandir($path, SCANDIR_SORT_NONE); if($allFiles !== false){ $files = array_filter($allFiles, function(string $filename) : bool{ return substr($filename, -4) === ".ini"; }); $result = []; foreach($files as $file){ $code = explode(".", $file)[0]; $strings = self::loadLang($path, $code); if(isset($strings["language.name"])){ $result[$code] = $strings["language.name"]; } } return $result; } } throw new LanguageNotFoundException("Language directory $path does not exist or is not a directory"); } /** @var string */ protected $langName; /** * @var string[] * @phpstan-var array */ protected $lang = []; /** * @var string[] * @phpstan-var array */ protected $fallbackLang = []; /** * @throws LanguageNotFoundException */ public function __construct(string $lang, ?string $path = null, string $fallback = self::FALLBACK_LANGUAGE){ $this->langName = strtolower($lang); if($path === null){ $path = \pocketmine\RESOURCE_PATH . "locale/"; } $this->lang = self::loadLang($path, $this->langName); $this->fallbackLang = self::loadLang($path, $fallback); } public function getName() : string{ return $this->get("language.name"); } public function getLang() : string{ return $this->langName; } /** * @return string[] * @phpstan-return array */ protected static function loadLang(string $path, string $languageCode) : array{ $file = $path . $languageCode . ".ini"; if(file_exists($file)){ return array_map('\stripcslashes', parse_ini_file($file, false, INI_SCANNER_RAW)); } throw new LanguageNotFoundException("Language \"$languageCode\" not found"); } /** * @param (float|int|string)[] $params */ public function translateString(string $str, array $params = [], ?string $onlyPrefix = null) : string{ $baseText = $this->get($str); $baseText = $this->parseTranslation(($onlyPrefix === null or strpos($str, $onlyPrefix) === 0) ? $baseText : $str, $onlyPrefix); foreach($params as $i => $p){ $baseText = str_replace("{%$i}", $this->parseTranslation((string) $p), $baseText, $onlyPrefix); } return $baseText; } public function translate(TextContainer $c) : string{ if($c instanceof TranslationContainer){ $baseText = $this->internalGet($c->getText()); $baseText = $this->parseTranslation($baseText ?? $c->getText()); foreach($c->getParameters() as $i => $p){ $baseText = str_replace("{%$i}", $this->parseTranslation($p), $baseText); } }else{ $baseText = $this->parseTranslation($c->getText()); } return $baseText; } protected function internalGet(string $id) : ?string{ return $this->lang[$id] ?? $this->fallbackLang[$id] ?? null; } public function get(string $id) : string{ return $this->internalGet($id) ?? $id; } protected function parseTranslation(string $text, ?string $onlyPrefix = null) : string{ $newString = ""; $replaceString = null; $len = strlen($text); for($i = 0; $i < $len; ++$i){ $c = $text[$i]; if($replaceString !== null){ $ord = ord($c); if( ($ord >= 0x30 and $ord <= 0x39) // 0-9 or ($ord >= 0x41 and $ord <= 0x5a) // A-Z or ($ord >= 0x61 and $ord <= 0x7a) or // a-z $c === "." or $c === "-" ){ $replaceString .= $c; }else{ if(($t = $this->internalGet(substr($replaceString, 1))) !== null and ($onlyPrefix === null or strpos($replaceString, $onlyPrefix) === 1)){ $newString .= $t; }else{ $newString .= $replaceString; } $replaceString = null; if($c === "%"){ $replaceString = $c; }else{ $newString .= $c; } } }elseif($c === "%"){ $replaceString = $c; }else{ $newString .= $c; } } if($replaceString !== null){ if(($t = $this->internalGet(substr($replaceString, 1))) !== null and ($onlyPrefix === null or strpos($replaceString, $onlyPrefix) === 1)){ $newString .= $t; }else{ $newString .= $replaceString; } } return $newString; } }