Added multilanguage support & improved downloading

This commit is contained in:
Filip Znachor 2023-11-01 18:23:30 +01:00
parent 0a8cb0f686
commit 3b06aa4eed
9 changed files with 114 additions and 20 deletions

View file

@ -5,8 +5,8 @@ define("UPTIME_KUMA_PAGE", "public");
define("ENABLE_TWIG_CACHE", false);
define("DATE_FORMAT", "M j, Y, g:i a");
define("TIMEZONE", "Etc/UTC");
define("DEFAULT_LANGUAGE", "en");
define("MONITOR_OPTIONS", [
4 => ["rich" => true]

44
controller/locale.php Normal file
View file

@ -0,0 +1,44 @@
<?php namespace Locale;
class Locale {
private array $strings = [];
public function __construct(string $defaultLang) {
$lang = explode(";", $_SERVER['HTTP_ACCEPT_LANGUAGE'])[0];
$languages = array_merge([$defaultLang], array_reverse(explode(",", $lang)));
foreach ($languages as $lang) {
$this->load_lang($lang);
}
}
private function load_lang(string $lang) {
$path = "../lang/" . basename("$lang.json");
if (is_file($path)) {
$content = file_get_contents($path);
if (!$content) return;
$arr = json_decode($content, true);
if ($arr) $this->strings = array_merge($this->strings, $arr);
}
}
public function get(string $msg, ?array $data = []) {
if (array_key_exists($msg, $this->strings)) {
$msg = $this->strings[$msg];
foreach ($data as $key => $value) {
$msg = str_replace("{{{$key}}}", $value, $msg);
}
}
return $msg;
}
public function t() {
return new \Twig\TwigFilter('t', function ($msg, $data = []) {
return $this->get($msg, $data);
});
}
}

View file

@ -3,15 +3,43 @@
require_once("../vendor/autoload.php");
require_once("../model/page.php");
require_once(__DIR__ . "/filters.php");
require_once(__DIR__ . "/locale.php");
class UptimeStatus {
private array $data;
public function load_data() {
$page = json_decode(file_get_contents(UPTIME_KUMA_URL . "/api/status-page/" . UPTIME_KUMA_PAGE), true);
$heartbeat = json_decode(file_get_contents(UPTIME_KUMA_URL . "/api/status-page/heartbeat/" . UPTIME_KUMA_PAGE), true);
$this->data = Page::convert($page, $heartbeat)->export();
$urls = [
UPTIME_KUMA_URL . "/api/status-page/" . UPTIME_KUMA_PAGE,
UPTIME_KUMA_URL . "/api/status-page/heartbeat/" . UPTIME_KUMA_PAGE
];
$arr = $this->download($urls);
$this->data = Page::convert($arr[0], $arr[1])->export();
}
private function download(array $urls): array {
$chs = []; $data = [];
$mh = curl_multi_init();
foreach ($urls as $url) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_multi_add_handle($mh, $ch);
array_push($chs, $ch);
}
do {
$status = curl_multi_exec($mh, $active);
if ($active) curl_multi_select($mh);
} while ($active && $status == CURLM_OK);
foreach ($chs as $ch) {
array_push($data, json_decode(curl_multi_getcontent($ch), true));
curl_multi_remove_handle($mh, $ch);
}
curl_multi_close($mh);
return $data;
}
public function raw() {
@ -19,15 +47,23 @@ class UptimeStatus {
}
public function display() {
$twig_config = [];
if (ENABLE_TWIG_CACHE) $twig_config["cache"] = "../cache/twig/";
$loader = new \Twig\Loader\FilesystemLoader("../view/");
$twig = new \Twig\Environment($loader, $twig_config);
$twig->addFilter(\Filters\timediffmin());
$twig->addFilter(\Filters\isof());
$locale = new \Locale\Locale(DEFAULT_LANGUAGE);
$twig->addFilter($locale->t());
$ext = $twig->getExtension(\Twig\Extension\CoreExtension::class);
$ext->setDateFormat($locale->get("dateformat"));
$ext->setTimezone(TIMEZONE);
echo $twig->render('index.twig', $this->data);
}

10
lang/cs.json Normal file
View file

@ -0,0 +1,10 @@
{
"header.title.all": "Všechny služby běží",
"header.title.some": "Některé služby neběží",
"header.title.none": "Všechny služby jsou offline",
"header.updated": "Poslední aktualizace {{date}}.",
"heartbeats.now": "nyní",
"heartbeats.ago": "před {{minutes}} minutami",
"monitor.uptime": "<b>{{pct}}%</b> uptime",
"dateformat": "j. m. Y G:i"
}

10
lang/en.json Normal file
View file

@ -0,0 +1,10 @@
{
"header.title.all": "All services are online",
"header.title.some": "Some services are down",
"header.title.none": "All services are down",
"header.updated": "Last updated on {{date}}.",
"heartbeats.now": "now",
"heartbeats.ago": "{{minutes}} minutes ago",
"monitor.uptime": "<b>{{pct}}%</b> uptime",
"dateformat": "M j, Y, g:i a"
}

View file

@ -8,13 +8,9 @@ class Page {
private int $online = 0;
private int $total = 0;
private array $groups = [];
private string $date_format;
private string $timezone;
public function __construct(array $page) {
$this->page = $page;
$this->date_format = DATE_FORMAT;
$this->timezone = TIMEZONE;
}
public function add_group(Group $group) {
@ -28,9 +24,7 @@ class Page {
"page" => $this->page,
"online" => $this->online,
"total" => $this->total,
"groups" => $this->groups,
"date_format" => $this->date_format,
"timezone" => $this->timezone
"groups" => $this->groups
];
}

View file

@ -3,21 +3,21 @@
{% if online == total %}
<div class="icon">{{ include("./icon/success.svg") }}</div>
<h1>All services are online</h1>
<h1>{{ "header.title.all" | t }}</h1>
{% elseif online == 0 %}
<div class="icon">{{ include("./icon/error.svg") }}</div>
<h1>All services are down</h1>
<h1>{{ "header.title.none" | t }}</h1>
{% else %}
<div class="icon">{{ include("./icon/warning.svg") }}</div>
<h1>Some services are down</h1>
<h1>{{ "header.title.some" | t }}</h1>
{% endif %}
<p>
Last updated on {{ now | date(date_format, timezone) }}.
{{ "header.updated" | t({date: now | date}) }}
</p>
</div>
</header>

View file

@ -5,7 +5,7 @@
{% endfor %}
</div>
<div class="time">
<div>{{ (monitor.heartbeats | first).time | timediffmin((monitor.heartbeats | last).time) }} min</div>
<div>now</div>
<div>{{ "heartbeats.ago" | t({minutes: (monitor.heartbeats | first).time | timediffmin((monitor.heartbeats | last).time)}) }}</div>
<div>{{ "heartbeats.now" | t }}</div>
</div>
</div>

View file

@ -15,7 +15,7 @@
{{ monitor.name }}
</h4>
<div class="uptime">
<b>{{ (monitor.uptime * 100) | number_format(1, '.') }}%</b> uptime
{{ "monitor.uptime" | t({pct: (monitor.uptime * 100) | number_format(1, '.')}) | raw }}
</div>
</div>
{% if monitor.opt.rich %}