ch1p_io_web/engine/strings.php
2024-01-31 20:45:40 +03:00

138 lines
3.6 KiB
PHP

<?php
enum DeclensionCase: string {
case GEN = 'Gen';
case DAT = 'Dat';
case ACC = 'Acc';
case INS = 'Ins';
case ABL = 'Abl';
}
enum NameSex: int {
case MALE = 0;
case FEMALE = 1;
}
enum NameType: int {
case FIRST_NAME = 0;
case LAST_NAME = 1;
}
class StringsBase implements ArrayAccess {
protected array $data = [];
function offsetSet(mixed $offset, mixed $value): void {
throw new RuntimeException('Not implemented');
}
function offsetExists(mixed $offset): bool {
return isset($this->data[$offset]);
}
function offsetUnset(mixed $offset): void {
throw new RuntimeException('Not implemented');
}
function offsetGet(mixed $offset): mixed {
if (!isset($this->data[$offset])) {
logError(__METHOD__.': '.$offset.' not found');
return '{'.$offset.'}';
}
return $this->data[$offset];
}
function get(string $key, mixed ...$sprintf_args): string|array {
$val = $this[$key];
if (!empty($sprintf_args)) {
array_unshift($sprintf_args, $val);
return call_user_func_array('sprintf', $sprintf_args);
} else {
return $val;
}
}
function num(string $key, int $num, array$opts = []) {
$s = $this[$key];
$default_opts = [
'format' => true,
'format_delim' => ' ',
'lang' => 'ru',
];
$opts = array_merge($default_opts, $opts);
switch ($opts['lang']) {
case 'ru':
$n = $num % 100;
if ($n > 19)
$n %= 10;
if ($n == 1) {
$word = 0;
} elseif ($n >= 2 && $n <= 4) {
$word = 1;
} elseif ($num == 0 && count($s) == 4) {
$word = 3;
} else {
$word = 2;
}
break;
default:
if ($num == 0 && count($s) == 4) {
$word = 3;
} else {
$word = $num == 1 ? 0 : 1;
}
break;
}
// if zero
if ($word == 3) {
return $s[3];
}
if (is_callable($opts['format'])) {
$num = $opts['format']($num);
} else if ($opts['format'] === true) {
$num = formatNumber($num, $opts['format_delim']);
}
return sprintf($s[$word], $num);
}
}
class Strings extends StringsBase {
private static ?Strings $instance = null;
protected array $loadedPackages = [];
private function __construct() {}
protected function __clone() {}
public static function getInstance(): self {
if (is_null(self::$instance))
self::$instance = new self();
return self::$instance;
}
function load(string ...$pkgs): array {
$keys = [];
foreach ($pkgs as $name) {
$raw = yaml_parse_file(APP_ROOT.'/strings/'.$name.'.yaml');
$this->data = array_merge($this->data, $raw);
$keys = array_merge($keys, array_keys($raw));
$this->loadedPackages[$name] = true;
}
return $keys;
}
function flex(string $s, DeclensionCase $case, NameSex $sex, NameType $type): string {
$s = iconv('utf-8', 'cp1251', $s);
$s = vkflex($s, $case->value, $sex->value, 0, $type->value);
return iconv('cp1251', 'utf-8', $s);
}
function search(string $regexp): array {
return preg_grep($regexp, array_keys($this->data));
}
}