MDNodaHelpers/src/NodaTimeAutotranslater.php

306 lines
8.5 KiB
PHP
Raw Normal View History

2020-09-18 18:48:40 +02:00
<?PHP
/**
* Controls automatic translation of times.
*
* @author Joshua Ramon Enslin <joshua@museum-digital.de>
*/
declare(strict_types = 1);
require_once __DIR__ . '/inc/datesByCountry.php';
/**
* Autotranslater class for times.
*/
2020-09-18 21:38:49 +02:00
final class NodaTimeAutotranslater {
2020-09-18 18:48:40 +02:00
const USECASE_MONTH = 1;
const USECASE_DAY = 2;
const TRANSLATABLE_NOT = 0;
const TRANSLATABLE_AS_MONTH_DAY = 1;
const TRANSLATABLE_AS_YEAR_WITH_SUFFIX = 2;
2020-09-18 18:48:40 +02:00
const LANGS_TO_LOCALES = [
'ar' => 'ar_SY.utf8',
'de' => 'de_DE.utf8',
'en' => 'en_US.utf8',
'es' => 'es_ES.utf8',
'fa' => 'fa_IR.UTF-8',
'fr' => 'fr_FR.utf8',
'hu' => 'hu_HU.utf8',
'id' => 'id_ID.utf8',
'it' => 'it_IT.utf8',
'ka' => 'ka_GE.UTF-8',
'ko' => 'ko_KR.UTF-8',
'pl' => 'pl_PL.utf8',
'pt' => 'pt_BR.utf8',
'ro' => 'ro_RO.UTF-8',
'ru' => 'ru_RU.UTF-8',
'ta' => 'ta_IN.UTF-8',
'tl' => 'tl_PH.utf8',
'tr' => 'tr_TR.utf8',
// Languages that don't really need a specific locale
'ja' => 'en_US.utf8',
'zh' => 'en_US.utf8',
];
const LANGS_SINGLE_YEAR_FORMAT = [
'ar' => '%s',
'de' => '%s',
'en' => '%s',
'es' => '%s',
'fa' => '%s',
'fr' => '%s',
'hu' => '%s',
'id' => '%s',
'it' => '%s',
'ka' => '%s',
'ko' => '%s년',
'pl' => '%s',
'pt' => '%s',
'ro' => '%s',
'ru' => '%s',
'ta' => '%s',
'tl' => '%s',
'tr' => '%s',
// Languages that don't really need a specific locale
'ja' => '%s年',
'zh' => '%s年',
];
const LANGS_YEARSPAN_FORMAT = [
'ar' => '%s-%s',
'de' => '%s-%s',
'en' => '%s-%s',
'es' => '%s-%s',
'fa' => '%s-%s',
'fr' => '%s-%s',
'hu' => '%s-%s',
'id' => '%s-%s',
'it' => '%s-%s',
'ka' => '%s-%s',
'ko' => '%s년-%s년',
'pl' => '%s-%s',
'pt' => '%s-%s',
'ro' => '%s-%s',
'ru' => '%s-%s',
'ta' => '%s-%s',
'tl' => '%s-%s',
'tr' => '%s-%s',
// Languages that don't really need a specific locale
'ja' => '%s年から%s年',
'zh' => '%s年至%s年',
];
const LANGS_TO_BCE_FORMAT = [
'ar' => '-%s',
'de' => '%s v. Chr.',
'en' => '%s BC',
'es' => '%s a.C.',
'fa' => '-%s',
'fr' => '%s av. J.-C.',
'hu' => 'Kr. e. %s',
'id' => '%s SM',
'it' => '%s a.C.',
'ka' => 'ძვ. წ. %s წ',
'ko' => '기원전%s',
'pl' => '%s pne',
'pt' => '%s AC',
'ro' => '%s î.Hr.',
'ru' => '%s г. до н.э.',
'ta' => 'கிமு %s',
'tl' => '%s BC',
'tr' => 'MÖ %s',
// Languages that don't really need a specific locale
'ja' => '紀元前%s',
'zh' => '公元前%s',
];
const LANGS_TO_CE_FORMAT = [
'ar' => '%s',
'de' => '%s n. Chr.',
'en' => '%s CE',
'es' => '%s d.C.',
'fa' => '%s',
'fr' => '%s ap. J.-C.',
'hu' => '%s',
'id' => '%s M.',
'it' => '%s d.C.',
'ka' => '%s წ',
'ko' => '%s',
'pl' => '%s n.e.',
'pt' => '%s dC',
'ro' => '%s',
'ru' => '%s',
'ta' => '%s பொ.ச.',
'tl' => '%s AD',
'tr' => '%s',
// Languages that don't really need a specific locale
'ja' => '西暦%s',
'zh' => '%s',
];
2020-09-18 18:48:40 +02:00
/** @var MDMysqli */
private MDMysqli $_mysqli_noda;
/** @var integer */
private int $_znum;
/** @var MDMysqliStmt */
private MDMysqliStmt $_insertStmt;
/**
* Checks if a time is translatable.
* Translatable times have either a counting time day and month or at least a month.
*
* @param string $zeit_beginn Beginn year.
* @param string $zeit_ende End year.
2020-09-18 18:48:40 +02:00
* @param string $zeit_zaehlzeit_monat Counting time month.
*
* @return integer
*/
public static function check_translatability(string $zeit_beginn, string $zeit_ende, string $zeit_zaehlzeit_monat):int {
if (intval($zeit_ende) >= 0 && intval($zeit_beginn) < 0) {
return self::TRANSLATABLE_NOT;
}
if (intval($zeit_ende) < 1000 || intval($zeit_ende) < 0 && intval($zeit_beginn) < 0) {
return self::TRANSLATABLE_AS_YEAR_WITH_SUFFIX;
}
// Conditions speaking against translatability.
else if (trim($zeit_zaehlzeit_monat, ", .0") === "") {
$output = self::TRANSLATABLE_NOT;
}
return self::TRANSLATABLE_AS_MONTH_DAY;
}
/**
* Translated years or timespans below 1000 CE.
*
* @param array<integer|string> $timeInfo Time information.
*
* @return void
2020-09-18 18:48:40 +02:00
*/
public function translateYearsWithSuffix(array $timeInfo):void {
$start = intval($timeInfo['zeit_beginn']);
$end = intval($timeInfo['zeit_ende']);
2020-09-18 18:48:40 +02:00
if ($start < 0 && $end < 0) {
$suffixMode = 2; // 2; // " v. Chr.";
}
else if ($end < 1000) {
$suffixMode = 1; // " n. Chr.";
2020-09-18 18:48:40 +02:00
}
else $suffixMode = 0;
foreach (self::LANGS_TO_CE_FORMAT as $tLang => $ceFormat) {
if ($start === $end) {
$year = sprintf(self::LANGS_SINGLE_YEAR_FORMAT[$tLang], (string)abs($start));
}
else $year = sprintf(self::LANGS_YEARSPAN_FORMAT[$tLang], (string)abs($start), (string)abs($end));
2020-09-18 18:48:40 +02:00
switch ($suffixMode) {
case 0:
$timeName = $year;
break;
case 1:
$timeName = sprintf($ceFormat, $year);
break;
case 2:
$timeName = sprintf(self::LANGS_TO_BCE_FORMAT[$tLang], $year);
break;
default:
throw new Exception("Unknown case encountered for time translations.");
}
$this->_insertStmt->bind_param("iss", $this->_znum, $tLang, $timeName);
$this->_insertStmt->execute();
}
2020-09-18 18:48:40 +02:00
}
/**
* Runs autotranslater.
*
* @param array<integer|string> $timeInfo Time information.
*
* @return void
*/
public function translate(array $timeInfo):void {
if (!($translation_type = self::check_translatability($timeInfo['zeit_beginn'], $timeInfo['zeit_ende'], (string)$timeInfo['zeit_zaehlzeit_monat']))) {
2020-09-18 18:48:40 +02:00
throw new MDgenericInvalidInputsException("Non-translatable date");
}
if ($translation_type === self::TRANSLATABLE_AS_YEAR_WITH_SUFFIX) {
$this->translateYearsWithSuffix($timeInfo);
return;
}
2020-09-18 21:38:49 +02:00
if (trim((string)$timeInfo['zeit_zaehlzeit_tag'], ", .0") === "") {
2020-09-18 18:48:40 +02:00
$dateStr = "{$timeInfo['zeit_zaehlzeit_jahr']}-{$timeInfo['zeit_zaehlzeit_monat']}-05 00:00:01";
$usecase = self::USECASE_MONTH;
2020-09-18 18:48:40 +02:00
}
else {
$dateStr = "{$timeInfo['zeit_zaehlzeit_jahr']}-{$timeInfo['zeit_zaehlzeit_monat']}-{$timeInfo['zeit_zaehlzeit_tag']} 00:00:01";
$usecase = self::USECASE_DAY;
2020-09-18 18:48:40 +02:00
}
$dateGeneral = strtotime($dateStr);
foreach (self::LANGS_TO_LOCALES as $tLang => $locale) {
setlocale(LC_TIME, $locale);
if ($locale !== setlocale(LC_TIME, "0")) continue;
if ($usecase === self::USECASE_MONTH) $tLangValue = strftime(getMonthFormatByLang($tLang), $dateGeneral ?: 0);
2020-09-18 21:38:49 +02:00
else { # if ($usecase === self::USECASE_DAY)
$tLangValue = strftime(getDateFormatByLang($tLang), $dateGeneral ?: 0);
}
2020-09-18 18:48:40 +02:00
$this->_insertStmt->bind_param("iss", $this->_znum, $tLang, $tLangValue);
$this->_insertStmt->execute();
}
}
/**
* Constructor.
*
* @param MDMysqli $mysqli_noda Database connection.
* @param integer $znum Time ID.
*
* @return void
*/
public function __construct(MDMysqli $mysqli_noda, int $znum) {
$this->_mysqli_noda = $mysqli_noda;
$this->_znum = $znum;
$this->_insertStmt = $mysqli_noda->do_prepare("INSERT INTO `zeit_translation`
(`zeit_id`, `trans_language`, `trans_name`)
VALUES
(?, ?, ?)");
}
/**
* Destructor.
*
* @return void
*/
public function __destruct() {
$this->_insertStmt->close();
}
}