Added multilanguage support & improved downloading
This commit is contained in:
parent
0a8cb0f686
commit
3b06aa4eed
|
@ -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
44
controller/locale.php
Normal 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);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
|
@ -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
10
lang/cs.json
Normal 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
10
lang/en.json
Normal 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"
|
||||
}
|
|
@ -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
|
||||
];
|
||||
}
|
||||
|
||||
|
|
|
@ -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>
|
|
@ -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>
|
|
@ -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 %}
|
||||
|
|
Loading…
Reference in a new issue