Merge remote-tracking branch 'origin/master' into notification-provider-pagertree

# Conflicts:
#	src/lang/en.json
pull/2871/head
Louis Lam 1 year ago
commit 71c800b880

@ -33,7 +33,7 @@ tsconfig.json
/ecosystem.config.js
/extra/healthcheck.exe
/extra/healthcheck
extra/exe-builder
### .gitignore content (commented rules are duplicated)
@ -48,6 +48,4 @@ dist-ssr
#!/data/.gitkeep
#.vscode
### End of .gitignore content

@ -0,0 +1,19 @@
---
name: "Security Issue"
about: "Just for alerting @louislam, do not provide any details here"
title: "Security Issue"
ref: "main"
labels:
- security
---
DO NOT PROVIDE ANY DETAILS HERE. Please privately report to https://github.com/louislam/uptime-kuma/security/advisories/new.
Why need this issue? It is because GitHub Advisory do not send a notification to @louislam, it is a workaround to do so.
Your GitHub Advisory URL:

3
.gitignore vendored

@ -20,3 +20,6 @@ cypress/screenshots
/extra/healthcheck.exe
/extra/healthcheck
/extra/healthcheck-armv7
extra/exe-builder/bin
extra/exe-builder/obj

@ -10,5 +10,6 @@
"color-function-notation": "legacy",
"shorthand-property-no-redundant-values": null,
"color-hex-length": null,
"declaration-block-no-redundant-longhand-properties": null
}
}

@ -235,12 +235,13 @@ https://github.com/louislam/uptime-kuma/issues?q=sort%3Aupdated-desc
1. Draft a release note
2. Make sure the repo is cleared
3. If the healthcheck is updated, remember to re-compile it: `npm run build-docker-builder-go`
3. `npm run release-final with env vars: `VERSION` and `GITHUB_TOKEN`
4. Wait until the `Press any key to continue`
5. `git push`
6. Publish the release note as 1.X.X
7. Press any key to continue
8. SSH to demo site server and update to 1.X.X
8. Deploy to the demo server: `npm run deploy-demo-server`
Checking:

@ -51,6 +51,7 @@ Uptime Kuma is now running on http://localhost:3001
Required Tools:
- [Node.js](https://nodejs.org/en/download/) >= 14
- [npm](https://docs.npmjs.com/cli/) >= 7
- [Git](https://git-scm.com/downloads)
- [pm2](https://pm2.keymetrics.io/) - For running Uptime Kuma in the background

@ -2,10 +2,15 @@
## Reporting a Vulnerability
Please report security issues to https://github.com/louislam/uptime-kuma/security/advisories/new.
1. Please report security issues to https://github.com/louislam/uptime-kuma/security/advisories/new.
1. Please also create a empty security issues for alerting me, as GitHub Advisory do not send a notification, I probably will miss without this. https://github.com/louislam/uptime-kuma/issues/new?assignees=&labels=help&template=security.md
Do not use the public issue tracker or discuss it in the public as it will cause more damage.
## Do you accept other 3rd-party bug bounty platforms?
At this moment, I DO NOT accept other bug bounty platforms, because I am not familiar with these platforms and someone have tried to send a phishing link to me by this already. To minimize my own risk, please report through GitHub Advisories only. I will ignore all 3rd-party bug bounty platforms emails.
## Supported Versions
### Uptime Kuma Versions

@ -0,0 +1,7 @@
-- You should not modify if this have pushed to Github, unless it does serious wrong with the db.
BEGIN TRANSACTION;
ALTER TABLE monitor
ADD description TEXT default null;
COMMIT;

@ -0,0 +1,13 @@
-- You should not modify if this have pushed to Github, unless it does serious wrong with the db.
BEGIN TRANSACTION;
CREATE TABLE [api_key] (
[id] INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
[key] VARCHAR(255) NOT NULL,
[name] VARCHAR(255) NOT NULL,
[user_id] INTEGER NOT NULL,
[created_date] DATETIME DEFAULT (DATETIME('now')) NOT NULL,
[active] BOOLEAN DEFAULT 1 NOT NULL,
[expires] DATETIME DEFAULT NULL,
CONSTRAINT FK_user FOREIGN KEY ([user_id]) REFERENCES [user]([id]) ON DELETE CASCADE ON UPDATE CASCADE
);
COMMIT;

@ -0,0 +1,12 @@
-- You should not modify if this have pushed to Github, unless it does serious wrong with the db.
BEGIN TRANSACTION;
ALTER TABLE monitor ADD http_body_encoding VARCHAR(25);
COMMIT;
BEGIN TRANSACTION;
UPDATE monitor SET http_body_encoding = 'json' WHERE (type = 'http' or type = 'keyword') AND http_body_encoding IS NULL;
COMMIT;

@ -71,7 +71,7 @@ RUN npm ci
EXPOSE 3000 3001
VOLUME ["/app/data"]
HEALTHCHECK --interval=60s --timeout=30s --start-period=180s --retries=5 CMD node extra/healthcheck.js
HEALTHCHECK --interval=60s --timeout=30s --start-period=180s --retries=5 CMD extra/healthcheck
CMD ["npm", "run", "start-pr-test"]
############################################

@ -22,7 +22,8 @@ if (! exists) {
fs.writeFileSync("package.json", JSON.stringify(pkg, null, 4) + "\n");
// Also update package-lock.json
childProcess.spawnSync("npm", [ "install" ]);
const npm = /^win/.test(process.platform) ? "npm.cmd" : "npm";
childProcess.spawnSync(npm, [ "install" ]);
commit(version);
tag(version);

@ -0,0 +1,59 @@
require("dotenv").config();
const { NodeSSH } = require("node-ssh");
const readline = require("readline");
const rl = readline.createInterface({ input: process.stdin,
output: process.stdout });
const prompt = (query) => new Promise((resolve) => rl.question(query, resolve));
(async () => {
try {
console.log("SSH to demo server");
const ssh = new NodeSSH();
await ssh.connect({
host: process.env.UPTIME_KUMA_DEMO_HOST,
port: process.env.UPTIME_KUMA_DEMO_PORT,
username: process.env.UPTIME_KUMA_DEMO_USERNAME,
privateKeyPath: process.env.UPTIME_KUMA_DEMO_PRIVATE_KEY_PATH
});
let cwd = process.env.UPTIME_KUMA_DEMO_CWD;
let result;
const version = await prompt("Enter Version: ");
result = await ssh.execCommand("git fetch --all", {
cwd,
});
console.log(result.stdout + result.stderr);
await prompt("Press any key to continue...");
result = await ssh.execCommand(`git checkout ${version} --force`, {
cwd,
});
console.log(result.stdout + result.stderr);
result = await ssh.execCommand("npm run download-dist", {
cwd,
});
console.log(result.stdout + result.stderr);
result = await ssh.execCommand("npm install --production", {
cwd,
});
console.log(result.stdout + result.stderr);
result = await ssh.execCommand("pm2 restart 1", {
cwd,
});
console.log(result.stdout + result.stderr);
} catch (e) {
console.log(e);
} finally {
rl.close();
}
})();
// When done reading prompt, exit program
rl.on("close", () => process.exit(0));

@ -47,6 +47,7 @@ function download(url) {
});
}
console.log("Done");
process.exit(0);
});
tarStream.on("error", () => {

@ -0,0 +1 @@
packages/

@ -0,0 +1,35 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />
</startup>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Diagnostics.DiagnosticSource" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.1.0" newVersion="4.0.1.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Diagnostics.Tracing" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.1.1.0" newVersion="4.1.1.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Reflection" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.1.1.0" newVersion="4.1.1.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Runtime" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.1.1.1" newVersion="4.1.1.1" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Runtime.InteropServices" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.1.1.0" newVersion="4.1.1.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>

@ -0,0 +1,84 @@
using System.ComponentModel;
namespace UptimeKuma {
partial class DownloadForm {
/// <summary>
/// Required designer variable.
/// </summary>
private IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing) {
if (disposing && (components != null)) {
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent() {
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(DownloadForm));
this.progressBar = new System.Windows.Forms.ProgressBar();
this.label = new System.Windows.Forms.Label();
this.labelData = new System.Windows.Forms.Label();
this.SuspendLayout();
//
// progressBar
//
this.progressBar.Location = new System.Drawing.Point(12, 12);
this.progressBar.Name = "progressBar";
this.progressBar.Size = new System.Drawing.Size(472, 41);
this.progressBar.TabIndex = 0;
//
// label
//
this.label.Location = new System.Drawing.Point(12, 59);
this.label.Name = "label";
this.label.Size = new System.Drawing.Size(472, 23);
this.label.TabIndex = 1;
this.label.Text = "Preparing...";
//
// labelData
//
this.labelData.Location = new System.Drawing.Point(12, 82);
this.labelData.Name = "labelData";
this.labelData.Size = new System.Drawing.Size(472, 23);
this.labelData.TabIndex = 2;
//
// DownloadForm
//
this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 16F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(496, 117);
this.Controls.Add(this.labelData);
this.Controls.Add(this.label);
this.Controls.Add(this.progressBar);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
this.MaximizeBox = false;
this.Name = "DownloadForm";
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
this.Text = "Uptime Kuma";
this.Load += new System.EventHandler(this.DownloadForm_Load);
this.ResumeLayout(false);
}
private System.Windows.Forms.Label labelData;
private System.Windows.Forms.Label label;
private System.Windows.Forms.ProgressBar progressBar;
#endregion
}
}

@ -0,0 +1,204 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.IO.Compression;
using System.Net;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using Newtonsoft.Json;
namespace UptimeKuma {
public partial class DownloadForm : Form {
private readonly Queue<DownloadItem> downloadQueue = new();
private readonly WebClient webClient = new();
private DownloadItem currentDownloadItem;
public DownloadForm() {
InitializeComponent();
}
private void DownloadForm_Load(object sender, EventArgs e) {
webClient.DownloadProgressChanged += DownloadProgressChanged;
webClient.DownloadFileCompleted += DownloadFileCompleted;
label.Text = "Reading latest version...";
// Read json from https://uptime.kuma.pet/version
var versionJson = new WebClient().DownloadString("https://uptime.kuma.pet/version");
var versionObj = JsonConvert.DeserializeObject<Version>(versionJson);
var nodeVersion = versionObj.nodejs;
var uptimeKumaVersion = versionObj.latest;
var hasUpdateFile = File.Exists("update");
if (!Directory.Exists("node")) {
downloadQueue.Enqueue(new DownloadItem {
URL = $"https://nodejs.org/dist/v{nodeVersion}/node-v{nodeVersion}-win-x64.zip",
Filename = "node.zip",
TargetFolder = "node"
});
}
if (!Directory.Exists("core") || hasUpdateFile) {
// It is update, rename the core folder to core.old
if (Directory.Exists("core")) {
// Remove the old core.old folder
if (Directory.Exists("core.old")) {
Directory.Delete("core.old", true);
}
Directory.Move("core", "core.old");
}
downloadQueue.Enqueue(new DownloadItem {
URL = $"https://github.com/louislam/uptime-kuma/archive/refs/tags/{uptimeKumaVersion}.zip",
Filename = "core.zip",
TargetFolder = "core"
});
File.WriteAllText("version.json", versionJson);
// Delete the update file
if (hasUpdateFile) {
File.Delete("update");
}
}
DownloadNextFile();
}
void DownloadNextFile() {
if (downloadQueue.Count > 0) {
var item = downloadQueue.Dequeue();
currentDownloadItem = item;
// Download if the zip file is not existing
if (!File.Exists(item.Filename)) {
label.Text = item.URL;
webClient.DownloadFileAsync(new Uri(item.URL), item.Filename);
} else {
progressBar.Value = 100;
label.Text = "Use local " + item.Filename;
DownloadFileCompleted(null, null);
}
} else {
npmSetup();
}
}
void npmSetup() {
labelData.Text = "";
var npm = "..\\node\\npm.cmd";
var cmd = $"{npm} ci --production & {npm} run download-dist & exit";
var startInfo = new ProcessStartInfo {
FileName = "cmd.exe",
Arguments = $"/k \"{cmd}\"",
RedirectStandardOutput = false,
RedirectStandardError = false,
RedirectStandardInput = true,
UseShellExecute = false,
CreateNoWindow = false,
WorkingDirectory = "core"
};
var process = new Process();
process.StartInfo = startInfo;
process.EnableRaisingEvents = true;
process.Exited += (_, e) => {
progressBar.Value = 100;
if (process.ExitCode == 0) {
Task.Delay(2000).ContinueWith(_ => {
Application.Restart();
});
label.Text = "Done";
} else {
label.Text = "Failed, exit code: " + process.ExitCode;
}
};
process.Start();
label.Text = "Installing dependencies and download dist files";
progressBar.Value = 50;
process.WaitForExit();
}
void DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e) {
progressBar.Value = e.ProgressPercentage;
var total = e.TotalBytesToReceive / 1024;
var current = e.BytesReceived / 1024;
if (total > 0) {
labelData.Text = $"{current}KB/{total}KB";
}
}
void DownloadFileCompleted(object sender, AsyncCompletedEventArgs e) {
Extract(currentDownloadItem);
DownloadNextFile();
}
void Extract(DownloadItem item) {
if (Directory.Exists(item.TargetFolder)) {
var dir = new DirectoryInfo(item.TargetFolder);
dir.Delete(true);
}
if (Directory.Exists("temp")) {
var dir = new DirectoryInfo("temp");
dir.Delete(true);
}
labelData.Text = $"Extracting {item.Filename}...";
ZipFile.ExtractToDirectory(item.Filename, "temp");
string[] dirList;
// Move to the correct level
dirList = Directory.GetDirectories("temp");
if (dirList.Length > 0) {
var dir = dirList[0];
// As sometime ExtractToDirectory is still locking the directory, loop until ok
while (true) {
try {
Directory.Move(dir, item.TargetFolder);
break;
} catch (Exception exception) {
Thread.Sleep(1000);
}
}
} else {
MessageBox.Show("Unexcepted Error: Cannot move extracted files, folder not found.");
}
labelData.Text = $"Extracted";
if (Directory.Exists("temp")) {
var dir = new DirectoryInfo("temp");
dir.Delete(true);
}
File.Delete(item.Filename);
}
}
public class DownloadItem {
public string URL { get; set; }
public string Filename { get; set; }
public string TargetFolder { get; set; }
}
}

@ -0,0 +1,377 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
AAABAAMAMDAAAAEAIACoJQAANgAAACAgAAABACAAqBAAAN4lAAAQEAAAAQAgAGgEAACGNgAAKAAAADAA
AABgAAAAAQAgAAAAAAAAJAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAA////BPT09Bfu7u4e8fHxJPPz8yv19fUy9fX1M/Pz8yvx8fEk9vb2HPPz8xXMzMwFAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP//
/wHv7+8f7u7uPPPz81Tx8fFs8fHxgPHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx
8YLx8fGB8fHxcfHx8V3x8fFI9PT0MOvr6w0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AADy8vIU8fHxS/Dw8Hbx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx
8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fFr9PT0R/Dw8CIAAAABAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAA8vLyFPHx8Vnx8fGB8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx
8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx
8YLx8fFs9fX1Mb+/vwQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAICAgALy8vI88fHxfvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx
8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx
8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvLy8nby8vI8gICAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAzMzMBfHx8Vrx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx
8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx
8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8vLyYf///wwAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADMzMwF8vLyYPHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx
8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx
8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx
8W/z8/MWAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADv7+9R8fHxgvHx8YLx8fGC8fHxgvHx
8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx
8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx
8YLx8fGC8fHxgvHx8YLw8PB26urqDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPLy8ijx8fGC8fHxgvHx
8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgu7w7Ifj79ud2u7PtNLrw83P677dzeu85c3r
u+rM67rwzOu68c7rverQ68Dj0uvD3NbuyM3b7c+64u7apujv5ZPx8fGC8fHxgvHx8YLx8fGC8fHxgvHx
8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxXgAAAAEAAAAAAAAAAAAAAAAAAAAA4+PjCfDw
8Hfx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLd7tSmzeu92MbqsvvG6bH/xumy/8fq
s//H6rP/yOq0/8jqtf/J6rb/yeq2/8rrt//K67j/y+u4/8vruf/M67r/zOu7/83ru//Q7MDx1u7Kz9/t
163s8OuJ8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgu/v7y8AAAAAAAAAAAAA
AAAAAAAA7u7uPfHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC5PDdl8jqtuTE6a7/xOmv/8Xp
sP/G6bH/xumx/8bpsv/H6rP/x+qz/8jqtP/I6rX/yeq2/8nqtv/K67f/yuu4/8vruP/L67n/zOu6/8zr
u//N67v/zey8/87svf/P67742e3Mx+jv5ZLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvDw
8HWAgIACAAAAAAAAAACqqqoD8vLyc/Hx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLf7degxOiu+cPo
rf/D6a7/xOmu/8Xpr//F6bD/xumx/8bpsf/G6bL/x+qz/8fqs//I6rT/yOq1/8nqtv/J6rb/yuu3/8rr
uP/L67j/y+u5/8zruv/M67v/zeu7/83svP/O7L3/zuy9/87svfzc7tK28fHxgvHx8YLx8fGC8fHxgvHx
8YLx8fGC8fHxgvHx8YLx8fEkAAAAAAAAAADz8/Mq8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgunv
5o3D6a/0wuis/8Lorf/D6K3/xOmu/8Tprv/F6a//xemw/8bpsf/G6bH/xumy/8fqs//H6rP/yOq0/8jq
tf/J6rb/yeq2/8rrt//K67j/y+u4/8vruf/M67r/zOu7/83ru//N7Lz/zuy9/87svf/O7L3/3e/TtPHx
8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLy8vJNAAAAAAAAAADy8vJM8fHxgvHx8YLx8fGC8fHxgvHx
8YLx8fGC8fHxgszqutDB6Kv/weir/8LorP/D6K3/w+it/8Tprv/E6a7/xemv/8XpsP/G6bH/xumx/8bp
sv/H6rP/x+qz/8jqtP/I6rX/yeq2/8nqtv/K67f/yuu4/8vruP/L67n/zOu6/8zru//N67v/zey8/87s
vf/O7L3/zuy++u3w6Yzx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLy8vJ1AAAAAAAAAADx8fFr8fHxgvHx
8YLx8fGC8fHxgvHx8YLx8fGC6O/kjsDoqvzA6Kr/weir/8Loq//C6Kz/w+it/8Porf/E6a7/xOmu/8Xp
r//F6bD/xumx/8bpsf/G6bL/x+qz/8fqtP/I6rT/yOq1/8nqtv/J6rb/yuu3/8rruP/L67n/y+u5/8zr
uv/M67v/zeu7/83svP/O7L3/zuy9/93u07Xx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC////Bv//
/wfx8fGB8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC1ezJsr/nqf/A56n/weiq/8Hoq//C6Kv/wuis/8Po
rf/D6K3/xOmu/8Pprv+856T/uOed/7bmmv+05Zf/teWZ/7jnnf+86KP/wOio/8fqs//J6rb/yeq2/8rr
t//K67j/y+u5/8vruf/M67r/zOu7/83ru//N7Lz/zuy9/9buyNLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx
8YLx8fGC8vLyE/Ly8hPx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGCy+q6zr/nqP/A56n/wOep/8Ho
qv/B6Kv/wuir/8LorP+u5Y//neF2/5bgav+V4Gr/luBr/5fhbP+Y4W7/meFv/5rhcf+b4nL/nOJ0/53i
dv+j5H//reaM/7nnnf/E6q//y+y4/8vruf/L67n/zOu6/8zru//N67v/zey8/9Lsxd/x8fGC8fHxgvHx
8YLx8fGC8fHxgvHx8YLx8fGC7+/vIPb29hzx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGCx+m03L/n
qP+/56j/wOep/8Dnqf/B6Kr/weir/7nmn/+R32T/kt9l/5PfZ/+U4Gj/leBq/5bga/+X4W3/mOFu/5nh
b/+a4XH/m+Jy/5zidP+d4nX/nuN3/5/jeP+f4nn/weqq/8rruP/L67n/y+u5/8zruv/M67v/zeu7/9Ls
w+Lx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8PDwI/Hx8SXx8fGC8fHxgvHx8YLx8fGC8fHxgvHx
8YLx8fGCxeix5L/nqP+/56j/v+eo/8Dnqf/A56n/weiq/7Pllv+Q3mP/kd9k/5LfZf+T32f/lOBo/5Xg
av+W4Gv/l+Ft/5jhbv+Z4W//muFx/5vicv+c4nT/neJ1/57jd/+f43j/xOmu/8rrt//K67j/y+u5/8vr
uf/M67r/zOu7/9Tsxtfx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC9PT0GO/v7yDx8fGC8fHxgvHx
8YLx8fGC8fHxgvHx8YLx8fGCx+m037/nqP+/56j/v+eo/7/nqP/A56n/wOip/7TmmP+P3mH/kN5j/5Hf
ZP+S32b/k99n/5TgaP+V4Gr/luBr/5fhbf+Y4W7/meFw/5rhcf+b4nL/nOJ0/53idf+h5Hz/yuu2/8nq
t//K67f/yuu4/8vruf/L67n/zOu6/9ftysrx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC7e3tDvT0
9Bfx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGCyOq117/nqP+/56j/v+eo/7/nqP+/56j/wOep/7vn
of+O3mD/j95h/5DeY/+R32T/kt9m/5PfZ/+U4Gj/leBq/5bga/+X4W3/mOFu/5nhcP+a4nH/m+Jy/5zi
dP+r5Yr/yOq1/8nqtv/J6rf/yuu3/8rruP/L67n/y+u5/9zu1LHx8fGC8fHxgvHx8YLx8fGC8fHxgvHx
8YLz8/OA////A+7u7g/x8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGCz+q+xb/nqP+/56j/v+eo/7/n
qP+/56j/v+eo/8Dnqf+S4Gb/jt5g/4/eYf+Q3mP/kd9k/5LfZv+T32f/lOBo/5Xgav+W4Gv/l+Ft/5jh
bv+Z4XD/muJx/5vic/+4553/yOq0/8jqtf/J6rb/yeq3/8rrt//K67j/y+u5/+bw4Zfx8fGC8fHxgvHx
8YLx8fGC8fHxgvHx8YLx8fFrAAAAAP///wHz8/N88fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC1+zMrr/n
qP+/56j/v+eo/7/nqP+/56j/v+eo/7/nqP+f4Xn/jd5f/47eYP+P3mH/kN5j/5HfZP+S32b/k99n/5Tg
af+V4Gr/luBr/5fhbf+Y4W7/meFw/5vic//F6rD/x+q0/8jqtP/I6rX/yeq2/8nqt//K67f/zOu88u/x
74Px8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLv7+9QAAAAAAAAAADw8PBm8fHxgvHx8YLx8fGC8fHxgvHx
8YLx8fGC5e7gk7/nqP+/56j/v+eo/7/nqP+/56j/v+eo/7/nqP+u5I//jN1d/43eX/+O3mD/j95h/5De
Y/+R32T/kt9m/5PfZ/+U4Gn/leBq/5bga/+X4W3/mOFu/6rliP/G6rL/x+qz/8fqtP/I6rT/yOq1/8nq
tv/J6rf/1OzGy/Hx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YL19fUzAAAAAAAAAADy8vJO8fHxgvHx
8YLx8fGC8fHxgvHx8YLx8fGC8fHxgsPoru2/56j/v+eo/7/nqP+/56j/v+eo/7/nqP++6Kf/j95i/4zd
Xf+N3l//jt5g/4/eYv+Q3mP/kd9k/5LfZv+T32f/lOBp/5Xgav+W4Gz/l+Ft/7voov/G6bL/xuqy/8fq
s//H6rT/yOq1/8jqtf/J6rb/4e/Zo/Hx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLw8PARAAAAAAAA
AADu7u4u8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgszpvMm/56j/v+eo/7/nqP+/56j/v+eo/7/n
qP+/56j/q+SL/4vdXP+M3V3/jd5f/47eYP+P3mL/kN9j/5HfZP+S32b/k99n/5Tgaf+V4Gr/qOOH/8Xp
sP/G6bH/xumy/8bqsv/H6rP/x+q0/8jqtf/K67jy8PHwhPHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx
8WoAAAAAAAAAAAAAAADo6OgL8fHxgfHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxguDv2J2/56j/v+eo/7/n
qP+/56j/v+eo/7/nqP+/56j/v+eo/6Xjgv+L3Vz/jN1d/43eX/+O3mD/j95i/5DfY/+R32T/kt9m/5Pf
Z/+k44D/xOmu/8XpsP/F6bD/xumx/8bpsv/G6rL/x+qz/8fqtP/W7cnB8fHxgvHx8YLx8fGC8fHxgvHx
8YLx8fGC8fHxgvPz80AAAAAAAAAAAAAAAAAAAAAA8PDwZ/Hx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx
8YLD6K/rv+eo/7/nqP+/56j/v+eo/7/nqP+/56j/v+eo/7/nqP+u5I//kt5n/4zdXf+N3l//jt5g/4/e
Yv+Q32P/luFs/67kj//D6K3/xOmu/8Tpr//F6bD/xemw/8bpsf/G6bL/xuqy/8fqtP7o7+WR8fHxgvHx
8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvPz8xYAAAAAAAAAAAAAAAAAAAAA8vLyPPHx8YLx8fGC8fHxgvHx
8YLx8fGC8fHxgvHx8YLV7ci0v+eo/7/nqP+/56j/v+eo/7/nqP+/56j/v+eo/7/nqP+/56j/wOio/7Xl
mv+u5I7/rOSM/67kj/+35pz/wumr/8Lorf/D6K3/w+it/8Tprv/E6a//xemw/8XpsP/G6bH/xumy/9Ds
wNPx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8vLyZQAAAAAAAAAAAAAAAAAAAAAAAAAA////DPHx
8YDx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGCx+m03L/nqP+/56j/v+eo/7/nqP+/56j/v+eo/7/n
qP+/56j/v+eo/7/nqP+/56j/wOep/8Doqv/B6Kr/weir/8LorP/C6K3/w+it/8Porv/E6a7/xOmv/8Xp
sP/F6bD/yOq18uvw6Yvx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC7+/vMQAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAPHx8Vzx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC6O/ij8LorPG/56j/v+eo/7/n
qP+/56j/v+eo/7/nqP+/56j/v+eo/7/nqP+/56j/v+eo/8Dnqf/A6Kr/weiq/8Hoq//C6Kz/wuit/8Po
rf/D6K7/xOmu/8Tpr//F6bH74u/anvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLw8PB6////BQAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAPPz8yrx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxguHu
2pnB56v2v+eo/7/nqP+/56j/v+eo/7/nqP+/56j/v+eo/7/nqP+/56j/v+eo/7/nqP/A56n/wOiq/8Ho
q//B6Kv/wuis/8Lorf/D6K3/w+mu/8Tprv3b7dKq8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx
8YLx8fFJAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHy8vJf8fHxgvHx8YLx8fGC8fHxgvHx
8YLx8fGC8fHxgvHx8YLi7tyXwumt8L/nqP+/56j/v+eo/7/nqP+/56j/v+eo/7/nqP+/56j/v+eo/7/n
qP+/56j/wOep/8Doqv/B6Kv/weir/8LorP/C6K3/xOiv+d7u1aTx8fGC8fHxgvHx8YLx8fGC8fHxgvHx
8YLx8fGC8fHxgvLy8nb///8KAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADv7+8Q8/Pze/Hx
8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC6/Dpiszqu82/56j/v+eo/7/nqP+/56j/v+eo/7/n
qP+/56j/v+eo/7/nqP+/56j/v+eo/8Dnqf/A6Kr/weir/8Hoq//H6bTj5e7elfHx8YLx8fGC8fHxgvHx
8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvPz8yoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAA9fX1MvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLe7tShx+mz3r/n
qP+/56j/v+eo/7/nqP+/56j/v+eo/7/nqP+/56j/v+eo/7/nqP/A56n/xumy5drtz6rv8e+D8fHxgvHx
8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8vLyTgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAPHx8Unx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx
8YLx8fGC8fHxgubv45DU68e2y+q6z8XoseTD6a7uweir9MPpru7F6bHly+q50tLsxLrl796U8fHxgvHx
8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLy8vJh////AwAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///wHx8fFZ8fHxgvHx8YLx8fGC8fHxgvHx
8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx
8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8Wzf398IAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8D8/PzVfHx
8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx
8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8PDwZujo
6AsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAA////AfHx8Ujx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx
8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx
8YLx8fFa////BQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADz8/Mp8vLydvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx
8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx
8YLx8fGC8/PzfPHx8TcAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////CvLy8lDz8/N/8fHxgvHx
8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx
8YLx8fGC8fHxgvPz84Hx8fFa8PDwEQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AADw8PAR8vLyTvHx8X3x8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx
8YLx8fGC8fHxgvHx8YLx8fF/8/PzVvT09BgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///wXz8/Mq8/PzU/Hx8XDx8fGB8fHxgvHx8YLx8fGC8fHxgvHx
8YLx8fGC8fHxgvHx8YLy8vJz8fHxWO/v7y////8IAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8G7e3tHfLy
8ifu7u4u8PDwNPT09C/y8vIo7+/vH+Pj4wkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAP///////wAA////////AAD///////8AAP//gAf//wAA//gAAD//AAD/wAAAB/8AAP+A
AAAB/wAA/gAAAAB/AAD8AAAAAD8AAPgAAAAAHwAA8AAAAAAPAADwAAAAAAcAAOAAAAAABwAA4AAAAAAD
AADAAAAAAAMAAMAAAAAAAwAAwAAAAAABAACAAAAAAAEAAIAAAAAAAQAAgAAAAAABAACAAAAAAAEAAIAA
AAAAAQAAgAAAAAABAACAAAAAAAMAAMAAAAAAAwAAwAAAAAADAADAAAAAAAMAAMAAAAAABwAAwAAAAAAH
AADgAAAAAAcAAOAAAAAADwAA4AAAAAAPAADwAAAAAB8AAPAAAAAAHwAA+AAAAAA/AAD8AAAAAD8AAPwA
AAAAfwAA/gAAAAD/AAD/AAAAAf8AAP+AAAAD/wAA/8AAAAf/AAD/8AAAH/8AAP/8AAA//wAA//8AAf//
AAD//+AP//8AAP///////wAA////////AAD///////8AACgAAAAgAAAAQAAAAAEAIAAAAAAAABAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAgICAAu/v7xD09PQX7u7uHvDw8CP29vYb8vLyFOrq6gwAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAICA
gALy8vIm7+/vT/Pz82fz8/N98fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvDw8Hrw8PBm7+/vUPT0
9C3o6OgLAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOPj
4wnz8/NC8vLydPHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx
8YLx8fGC8fHxgvHx8YHy8vJj8/PzKoCAgAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AADx8fEl8vLydfHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx
8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxcfHx8SUAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAA9PT0LfHx8YDx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx
8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8/PzgPLy8j0AAAABAAAAAAAA
AAAAAAAAAAAAAO3t7Rzx8fGA8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLr8OmM5O7emeTv
3Z7h79mj5fDem+nv45Tu8u6H8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvLy
8joAAAAAAAAAAAAAAAD///8E8fHxbvHx8YLx8fGC8fHxgvHx8YLx8fGC7vDshtns0K7N67zayeq288fq
s//I6rT/yOq1/8nqtv/K67f/y+u4/8vruf/P7L7w0+zF29vv0Lrn8OKX8fHxgvHx8YLx8fGC8fHxgvHx
8YLx8fGC8/PzfvPz8xUAAAAAAAAAAPX19TLx8fGC8fHxgvHx8YLx8fGC8fHxgt3u1KXF6rHzxOmv/8Xp
sP/G6bH/xumy/8fqs//I6rT/yOq1/8nqtv/K67f/y+u4/8vruf/M67v/zey8/87svf/S7MPj4u7Zp/Hx
8YLx8fGC8fHxgvHx8YLx8fGC8/PzVQAAAAAAAAAA8fHxavHx8YLx8fGC8fHxgvHx8YLf7defwuis/cPo
rf/E6a7/xOmv/8XpsP/G6bH/xumy/8fqs//I6rT/yOq1/8nqtv/K67f/y+u4/8vruv/M67v/zey8/87s
vf/N67z/3e7SufHx8YLx8fGC8fHxgvHx8YLz8/N8////Bf///w3x8fGC8fHxgvHx8YLx8fGC8fHxgsXp
sOnB6Kv/wuis/8Porf/E6a7/xOmv/8XpsP/G6bH/xumy/8fqs//I6rT/yOq1/8nqtv/K67f/y+u4/8vr
uv/M67v/zey8/87svf/O67z96/Hoj/Hx8YLx8fGC8fHxgvHx8YLy8vIm8/PzK/Hx8YLx8fGC8fHxgvHx
8YLg79icwOep/8Hoqv/B6Kv/wuis/8Porf/E6a7/wuit/73opP+76KL/u+eh/77opv/D6a3/yeu1/8nq
tv/K67f/y+u5/8zruv/M67v/zey8/87svf/d7tSz8fHxgvHx8YLx8fGC8fHxgvHx8Tby8vI68fHxgvHx
8YLx8fGC8fHxgtTrxre/56j/wOep/8Hoqv/B6Kv/uOad/53idv+V4Gn/leBq/5fhbP+Y4W//muFx/5vi
c/+e4Xb/puWD/7PmlP/D6a3/y+u5/8zruv/M67v/zey8/9rtzsHx8fGC8fHxgvHx8YLx8fGC8/PzQfPz
80Lx8fGC8fHxgvHx8YLx8fGC0OvAwr/nqP+/56j/wOep/8Hoqv+o44b/kd9k/5LfZv+U4Gj/leBq/5fh
bf+Y4W//muFx/5vic/+d4nX/n+N3/7fnm//K67j/y+u5/8zruv/M67v/2u3QvPHx8YLx8fGC8fHxgvHx
8YLy8vI98/PzP/Hx8YLx8fGC8fHxgvHx8YLQ6sK/v+eo/7/nqP+/56j/wOep/6jjhv+P3mL/kd9k/5Lf
Zv+U4Gj/leBr/5fhbf+Y4W//muFx/5zic/+d4nX/v+mm/8nqt//K67j/y+u5/8zruv/f79au8fHxgvHx
8YLx8fGC8fHxgvX19TLx8fE38fHxgvHx8YLx8fGC8fHxgtTrybO/56j/v+eo/7/nqP+/56j/sOSS/47e
YP+P3mL/kd9k/5LfZv+U4Gj/leBr/5fhbf+Z4W//muJx/5/jd//H6bP/yeq2/8nqt//K67j/y+u5/+nv
45Tx8fGC8fHxgvHx8YLx8fGC7+/vIPHx8SXx8fGC8fHxgvHx8YLx8fGC4e/Zm7/nqP+/56j/v+eo/7/n
qP+956X/jt5h/47eYP+P3mL/kd9k/5LfZv+U4Gn/luBr/5fhbf+Z4W//q+aK/8fqs//I6rT/yeq2/8nq
t//N7Lvw8fHxgvHx8YLx8fGC8fHxgvPz84D///8G6+vrDfHx8YLx8fGC8fHxgvHx8YLv8e+Dweis87/n
qP+/56j/v+eo/7/nqP+d4XX/jN1e/47eYP+P3mL/kd9k/5PfZ/+U4Gn/luBr/5fhbf+86KP/xuqy/8fq
s//I6rX/yeq2/9Tsx8nx8fGC8fHxgvHx8YLx8fGC8PDwaAAAAAAAAAAA8fHxbPHx8YLx8fGC8fHxgvHx
8YLM6rrMv+eo/7/nqP+/56j/v+eo/7blmv+N3V//jN1e/47eYP+Q3mL/kd9k/5PfZ/+U4Gn/qeSH/8Xp
sP/G6bH/xuqy/8fqs//I6rX/5fDem/Hx8YLx8fGC8fHxgvHx8YLz8/M/AAAAAAAAAADz8/NB8fHxgvHx
8YLx8fGC8fHxgt3s06O/56j/v+eo/7/nqP+/56j/v+eo/7Xmmf+U32n/jN1e/47eYP+Q3mL/k99o/6zk
i//D6a7/xemv/8XpsP/G6bH/xuqy/8vqu+jx8fGC8fHxgvHx8YLx8fGC8fHxgvPz8xUAAAAAAAAAAPT0
9Bfx8fGC8fHxgvHx8YLx8fGC8fHvg8Tpsee/56j/v+eo/7/nqP+/56j/v+eo/7/nqP+35pz/suWV/7Xm
mf/A6Kj/wuit/8Porf/E6a7/xemv/8XpsP/G6bH/3e3UqvHx8YLx8fGC8fHxgvHx8YLw8PBmAAAAAAAA
AAAAAAAAAAAAAPHx8W7x8fGC8fHxgvHx8YLx8fGC4u7cmMHnqvm/56j/v+eo/7/nqP+/56j/v+eo/7/n
qP+/56j/wOep/8Hoqv/C6Kz/wuit/8Porf/E6a7/xemv/9Hrwszx8fGC8fHxgvHx8YLx8fGC8fHxgvX1
9TEAAAAAAAAAAAAAAAAAAAAA7u7uO/Hx8YLx8fGC8fHxgvHx8YLx8fGC3e7SpMHoqfq/56j/v+eo/7/n
qP+/56j/v+eo/7/nqP+/56j/wOip/8Hoq//C6Kz/wuit/8Porf/O67zV8PHwhPHx8YLx8fGC8fHxgvHx
8YLy8vJ2////BQAAAAAAAAAAAAAAAAAAAACqqqoD8PDwafHx8YLx8fGC8fHxgvHx8YLx8fGC4O/YnMTo
ruy/56j/v+eo/7/nqP+/56j/v+eo/7/nqP+/56j/wOip/8Hoq//C6Kz90uvEwe/x74Px8fGC8fHxgvHx
8YLx8fGC8fHxgvPz8ykAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADz8/MW8fHxfPHx8YLx8fGC8fHxgvHx
8YLx8fGC8PLuhdXtyLXF6bHlv+eo/7/nqP+/56j/v+eo/7/nqP/B6Kv0zeq8zOXv4JTx8fGC8fHxgvHx
8YLx8fGC8fHxgvHx8YLy8vJNAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADy8vIm8fHxgPHx
8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLs8OmJ4e/Zm93u06Pf7def5+/hkvHx8YLx8fGC8fHxgvHx
8YLx8fGC8fHxgvHx8YLx8fGC8fHxXf///wIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AADy8vIo8/PzffHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx
8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8VnMzMwFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAD29vYb8fHxbvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx
8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvPz83/v7+9BgICAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADMzMwF8/PzQPLy8nnx8fGC8fHxgvHx8YLx8fGC8fHxgvHx
8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvPz84Hx8fFc9PT0GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////B/X19TLx8fFc8PDwevHx
8YLx8fGC8fHxgvHx8YLx8fGC8fHxgPHx8Wv09PRE9PT0FwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAA7+/vEPb29hvw8PAj7+/vH/T09Be/v78EAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////////////8B///wAA//wAAD/wAAAP4AAAB+AA
AAfAAAADwAAAA4AAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAADwAAAA8AAAAPAAAAH4AAAB+AA
AA/wAAAP+AAAH/gAAD/+AAB//wAB///AA///+B////////////8oAAAAEAAAACAAAAABACAAAAAAAAAE
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////CfDw8BH///8GAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgICAAu7u7i7x8fFe8PDwevHx8YLx8fGC8fHxgvDw
8Hvx8fFs7+/vT/Dw8CMAAAABAAAAAAAAAAAAAAAA5ubmCvLy8l/x8fGC8fHxgvHx8YLx8fGC8fHxgvHx
8YLx8fGC8fHxgvHx8YLx8fGC8/PzZu7u7g8AAAAAAAAAAPHx8V3x8fGC8fHxgunv5o7Z7c200+vFytTs
xc7W7cnH2+7QueLu2qbu8OyH8fHxgvHx8YLx8fFu////BfHx8STx8fGC8fHxgtrtzq3D6a/8xemw/8bp
sv/I6rT/yeq2/8vruP/M67v/z+u++Nzu0bjx8fGC8fHxgu/v7zDx8fFI8fHxguzw6ojC56z3wuis/8Tp
rv/E6q3/weiq/8fqsv/J6rb/y+u5/8zru//N67z/6/HpjfHx8YLy8vJN8fHxXPHx8YLg79icv+eo/8Ho
qv+k4n//lOBo/5fhbf+a4XH/n+J5/7Pmlv/L67n/zOu7/+Xw353x8fGC8fHxXvHx8Vrx8fGC4O3Zm7/n
qP+/56j/nuF3/5HfZP+U4Gj/l+Ft/5ricf+x5pL/yeq3/8vruf/r8emN8fHxgu/v70/x8fFK8fHxguzw
6ojA6Kn8v+eo/6njiP+O3mD/kd9k/5Tgaf+X4W3/vuim/8jqtP/N67zr8fHxgvHx8YLy8vI68/PzK/Hx
8YLx8fGCx+m03L/nqP++6Kb/meBw/47eYP+S32X/q+SL/8XpsP/G6rL/1+zLvvHx8YLz8/OB8PDwEdXV
1Qbx8fF98fHxgt/t1Z/A56j9v+eo/7/nqP+656H/vuim/8Lorf/E6a7/yOq18Ovw6Yvx8fGC8vLyYwAA
AAAAAAAA8fHxR/Hx8YLx8fGC2O3NrMDnqfq/56j/v+eo/7/nqP/B6Kv/xumy7OTu3Zfx8fGC8/PzgfLy
8icAAAAAAAAAAP///wPz8/Nm8fHxgvHx8YLo7+SO0+zFuczquszM6bzJ1+zMru7w7Ibx8fGC8fHxgvHx
8UcAAAAAAAAAAAAAAAAAAAAA4+PjCfHx8Vzx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgfPz
80D///8BAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB8/PzK/Ly8mDz8/N+8fHxgvHx8YLy8vJ68vLyUezs
7BsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAevr6w3j4+MJAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAP//AAD8fwAA4AcAAMADAACAAQAAgAEAAIABAACAAQAAgAEAAIAB
AADAAwAAwAMAAOAHAADwDwAA/n8AAP//AAA=
</value>
</data>
</root>

@ -0,0 +1,3 @@
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
<Costura />
</Weavers>

@ -0,0 +1,141 @@
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. -->
<xs:element name="Weavers">
<xs:complexType>
<xs:all>
<xs:element name="Costura" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:all>
<xs:element minOccurs="0" maxOccurs="1" name="ExcludeAssemblies" type="xs:string">
<xs:annotation>
<xs:documentation>A list of assembly names to exclude from the default action of "embed all Copy Local references", delimited with line breaks</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element minOccurs="0" maxOccurs="1" name="IncludeAssemblies" type="xs:string">
<xs:annotation>
<xs:documentation>A list of assembly names to include from the default action of "embed all Copy Local references", delimited with line breaks.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element minOccurs="0" maxOccurs="1" name="ExcludeRuntimeAssemblies" type="xs:string">
<xs:annotation>
<xs:documentation>A list of runtime assembly names to exclude from the default action of "embed all Copy Local references", delimited with line breaks</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element minOccurs="0" maxOccurs="1" name="IncludeRuntimeAssemblies" type="xs:string">
<xs:annotation>
<xs:documentation>A list of runtime assembly names to include from the default action of "embed all Copy Local references", delimited with line breaks.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element minOccurs="0" maxOccurs="1" name="Unmanaged32Assemblies" type="xs:string">
<xs:annotation>
<xs:documentation>A list of unmanaged 32 bit assembly names to include, delimited with line breaks.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element minOccurs="0" maxOccurs="1" name="Unmanaged64Assemblies" type="xs:string">
<xs:annotation>
<xs:documentation>A list of unmanaged 64 bit assembly names to include, delimited with line breaks.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element minOccurs="0" maxOccurs="1" name="PreloadOrder" type="xs:string">
<xs:annotation>
<xs:documentation>The order of preloaded assemblies, delimited with line breaks.</xs:documentation>
</xs:annotation>
</xs:element>
</xs:all>
<xs:attribute name="CreateTemporaryAssemblies" type="xs:boolean">
<xs:annotation>
<xs:documentation>This will copy embedded files to disk before loading them into memory. This is helpful for some scenarios that expected an assembly to be loaded from a physical file.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="IncludeDebugSymbols" type="xs:boolean">
<xs:annotation>
<xs:documentation>Controls if .pdbs for reference assemblies are also embedded.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="IncludeRuntimeReferences" type="xs:boolean">
<xs:annotation>
<xs:documentation>Controls if runtime assemblies are also embedded.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="UseRuntimeReferencePaths" type="xs:boolean">
<xs:annotation>
<xs:documentation>Controls whether the runtime assemblies are embedded with their full path or only with their assembly name.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="DisableCompression" type="xs:boolean">
<xs:annotation>
<xs:documentation>Embedded assemblies are compressed by default, and uncompressed when they are loaded. You can turn compression off with this option.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="DisableCleanup" type="xs:boolean">
<xs:annotation>
<xs:documentation>As part of Costura, embedded assemblies are no longer included as part of the build. This cleanup can be turned off.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="LoadAtModuleInit" type="xs:boolean">
<xs:annotation>
<xs:documentation>Costura by default will load as part of the module initialization. This flag disables that behavior. Make sure you call CosturaUtility.Initialize() somewhere in your code.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="IgnoreSatelliteAssemblies" type="xs:boolean">
<xs:annotation>
<xs:documentation>Costura will by default use assemblies with a name like 'resources.dll' as a satellite resource and prepend the output path. This flag disables that behavior.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="ExcludeAssemblies" type="xs:string">
<xs:annotation>
<xs:documentation>A list of assembly names to exclude from the default action of "embed all Copy Local references", delimited with |</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="IncludeAssemblies" type="xs:string">
<xs:annotation>
<xs:documentation>A list of assembly names to include from the default action of "embed all Copy Local references", delimited with |.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="ExcludeRuntimeAssemblies" type="xs:string">
<xs:annotation>
<xs:documentation>A list of runtime assembly names to exclude from the default action of "embed all Copy Local references", delimited with |</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="IncludeRuntimeAssemblies" type="xs:string">
<xs:annotation>
<xs:documentation>A list of runtime assembly names to include from the default action of "embed all Copy Local references", delimited with |.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="Unmanaged32Assemblies" type="xs:string">
<xs:annotation>
<xs:documentation>A list of unmanaged 32 bit assembly names to include, delimited with |.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="Unmanaged64Assemblies" type="xs:string">
<xs:annotation>
<xs:documentation>A list of unmanaged 64 bit assembly names to include, delimited with |.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="PreloadOrder" type="xs:string">
<xs:annotation>
<xs:documentation>The order of preloaded assemblies, delimited with |.</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:complexType>
</xs:element>
</xs:all>
<xs:attribute name="VerifyAssembly" type="xs:boolean">
<xs:annotation>
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="VerifyIgnoreCodes" type="xs:string">
<xs:annotation>
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="GenerateXsd" type="xs:boolean">
<xs:annotation>
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:complexType>
</xs:element>
</xs:schema>

@ -0,0 +1,243 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using Microsoft.Win32;
using Newtonsoft.Json;
using UptimeKuma.Properties;
namespace UptimeKuma {
static class Program {
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main(string[] args) {
var cwd = Path.GetDirectoryName(Application.ExecutablePath);
if (cwd != null) {
Environment.CurrentDirectory = cwd;
}
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new UptimeKumaApplicationContext());
}
}
public class UptimeKumaApplicationContext : ApplicationContext
{
private static Mutex mutex = null;
const string appName = "Uptime Kuma";
private NotifyIcon trayIcon;
private Process process;
private MenuItem statusMenuItem;
private MenuItem runWhenStarts;
private MenuItem openMenuItem;
private RegistryKey registryKey = Registry.CurrentUser.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", true);
public UptimeKumaApplicationContext() {
// Single instance only
bool createdNew;
mutex = new Mutex(true, appName, out createdNew);
if (!createdNew) {
return;
}
var startingText = "Starting server...";
trayIcon = new NotifyIcon();
trayIcon.Text = startingText;
runWhenStarts = new MenuItem("Run when system starts", RunWhenStarts);
runWhenStarts.Checked = registryKey.GetValue(appName) != null;
statusMenuItem = new MenuItem(startingText);
statusMenuItem.Enabled = false;
openMenuItem = new MenuItem("Open", Open);
openMenuItem.Enabled = false;
trayIcon.Icon = Icon.ExtractAssociatedIcon(Assembly.GetExecutingAssembly().Location);
trayIcon.ContextMenu = new ContextMenu(new MenuItem[] {
statusMenuItem,
openMenuItem,
//new("Debug Console", DebugConsole),
runWhenStarts,
new("Check for Update...", CheckForUpdate),
new("Visit GitHub...", VisitGitHub),
new("About", About),
new("Exit", Exit),
});
trayIcon.MouseDoubleClick += new MouseEventHandler(Open);
trayIcon.Visible = true;
var hasUpdateFile = File.Exists("update");
if (!hasUpdateFile && Directory.Exists("core") && Directory.Exists("node") && Directory.Exists("core/node_modules") && Directory.Exists("core/dist")) {
// Go go go
StartProcess();
} else {
DownloadFiles();
}
}
void DownloadFiles() {
var form = new DownloadForm();
form.Closed += Exit;
form.Show();
}
private void RunWhenStarts(object sender, EventArgs e) {
if (registryKey == null) {
MessageBox.Show("Error: Unable to set startup registry key.");
return;
}
if (runWhenStarts.Checked) {
registryKey.DeleteValue(appName, false);
runWhenStarts.Checked = false;
} else {
registryKey.SetValue(appName, Application.ExecutablePath);
runWhenStarts.Checked = true;
}
}
void StartProcess() {
var startInfo = new ProcessStartInfo {
FileName = "node/node.exe",
Arguments = "server/server.js --data-dir=\"../data/\"",
RedirectStandardOutput = false,
RedirectStandardError = false,
UseShellExecute = false,
CreateNoWindow = true,
WorkingDirectory = "core"
};
process = new Process();
process.StartInfo = startInfo;
process.EnableRaisingEvents = true;
process.Exited += ProcessExited;
try {
process.Start();
//Open(null, null);
// Async task to check if the server is ready
Task.Run(() => {
var runningText = "Server is running";
using TcpClient tcpClient = new TcpClient();
while (true) {
try {
tcpClient.Connect("127.0.0.1", 3001);
statusMenuItem.Text = runningText;
openMenuItem.Enabled = true;
trayIcon.Text = runningText;
break;
} catch (Exception) {
System.Threading.Thread.Sleep(2000);
}
}
});
} catch (Exception e) {
MessageBox.Show("Startup failed: " + e.Message, "Uptime Kuma Error");
}
}
void StopProcess() {
process?.Kill();
}
void Open(object sender, EventArgs e) {
Process.Start("http://localhost:3001");
}
void DebugConsole(object sender, EventArgs e) {
}
void CheckForUpdate(object sender, EventArgs e) {
var needUpdate = false;
// Check version.json exists
if (File.Exists("version.json")) {
// Load version.json and compare with the latest version from GitHub
var currentVersionObj = JsonConvert.DeserializeObject<Version>(File.ReadAllText("version.json"));
var versionJson = new WebClient().DownloadString("https://uptime.kuma.pet/version");
var latestVersionObj = JsonConvert.DeserializeObject<Version>(versionJson);
// Compare version, if the latest version is newer, then update
if (new System.Version(latestVersionObj.latest).CompareTo(new System.Version(currentVersionObj.latest)) > 0) {
var result = MessageBox.Show("A new version is available. Do you want to update?", "Update", MessageBoxButtons.YesNo);
if (result == DialogResult.Yes) {
// Create a empty file `update`, so the app will download the core files again at startup
File.Create("update").Close();
trayIcon.Visible = false;
process?.Kill();
// Restart the app, it will download the core files again at startup
Application.Restart();
}
} else {
MessageBox.Show("You are using the latest version.");
}
}
}
void VisitGitHub(object sender, EventArgs e)
{
Process.Start("https://github.com/louislam/uptime-kuma");
}
void About(object sender, EventArgs e)
{
MessageBox.Show("Uptime Kuma Windows Runtime v1.0.0" + Environment.NewLine + "© 2023 Louis Lam", "Info");
}
void Exit(object sender, EventArgs e)
{
// Hide tray icon, otherwise it will remain shown until user mouses over it
trayIcon.Visible = false;
process?.Kill();
Application.Exit();
}
void ProcessExited(object sender, EventArgs e) {
if (process.ExitCode != 0) {
var line = "";
while (!process.StandardOutput.EndOfStream)
{
line += process.StandardOutput.ReadLine();
}
MessageBox.Show("Uptime Kuma exited unexpectedly. Exit code: " + process.ExitCode + " " + line);
}
trayIcon.Visible = false;
Application.Exit();
}
}
}

@ -0,0 +1,36 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("Uptime Kuma")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Uptime Kuma")]
[assembly: AssemblyCopyright("Copyright © 2023 Louis Lam")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("2DB53988-1D93-4AC0-90C4-96ADEAAC5C04")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

@ -0,0 +1,62 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace UptimeKuma.Properties {
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// This class was auto-generated by the StronglyTypedResourceBuilder
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder",
"4.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance",
"CA1811:AvoidUncalledPrivateCode")]
internal Resources() {
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState
.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager {
get {
if ((resourceMan == null)) {
global::System.Resources.ResourceManager temp =
new global::System.Resources.ResourceManager("UptimeKuma.Properties.Resources",
typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState
.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
get { return resourceCulture; }
set { resourceCulture = value; }
}
}
}

@ -0,0 +1,117 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

@ -0,0 +1,23 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace UptimeKuma.Properties {
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute(
"Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
private static Settings defaultInstance =
((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
public static Settings Default {
get { return defaultInstance; }
}
}
}

@ -0,0 +1,7 @@
<?xml version='1.0' encoding='utf-8'?>
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)">
<Profiles>
<Profile Name="(Default)" />
</Profiles>
<Settings />
</SettingsFile>

@ -0,0 +1,212 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="packages\Costura.Fody.5.7.0\build\Costura.Fody.props" Condition="Exists('packages\Costura.Fody.5.7.0\build\Costura.Fody.props')" />
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{2DB53988-1D93-4AC0-90C4-96ADEAAC5C04}</ProjectGuid>
<OutputType>WinExe</OutputType>
<RootNamespace>UptimeKuma</RootNamespace>
<AssemblyName>uptime-kuma</AssemblyName>
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<Deterministic>true</Deterministic>
<ApplicationIcon>..\..\public\favicon.ico</ApplicationIcon>
<LangVersion>9</LangVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup>
<ApplicationManifest>app.manifest</ApplicationManifest>
</PropertyGroup>
<PropertyGroup>
<PostBuildEvent>COPY "$(SolutionDir)bin\Debug\uptime-kuma.exe" "%UserProfile%\Desktop\uptime-kuma-win64\"</PostBuildEvent>
</PropertyGroup>
<ItemGroup>
<Reference Include="Costura, Version=5.7.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>packages\Costura.Fody.5.7.0\lib\netstandard1.0\Costura.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Win32.Primitives, Version=4.0.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>packages\Microsoft.Win32.Primitives.4.3.0\lib\net46\Microsoft.Win32.Primitives.dll</HintPath>
</Reference>
<Reference Include="mscorlib" />
<Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>packages\Newtonsoft.Json.13.0.2\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.AppContext, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>packages\System.AppContext.4.3.0\lib\net463\System.AppContext.dll</HintPath>
</Reference>
<Reference Include="System.Buffers, Version=4.0.3.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>packages\System.Buffers.4.5.1\lib\net461\System.Buffers.dll</HintPath>
</Reference>
<Reference Include="System.ComponentModel.Composition" />
<Reference Include="System.Console, Version=4.0.1.1, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>packages\System.Console.4.3.1\lib\net46\System.Console.dll</HintPath>
</Reference>
<Reference Include="System.Core" />
<Reference Include="System.Diagnostics.DiagnosticSource, Version=7.0.0.1, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>packages\System.Diagnostics.DiagnosticSource.7.0.1\lib\net462\System.Diagnostics.DiagnosticSource.dll</HintPath>
</Reference>
<Reference Include="System.Diagnostics.Tracing, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>packages\System.Diagnostics.Tracing.4.3.0\lib\net462\System.Diagnostics.Tracing.dll</HintPath>
</Reference>
<Reference Include="System.Globalization.Calendars, Version=4.0.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>packages\System.Globalization.Calendars.4.3.0\lib\net46\System.Globalization.Calendars.dll</HintPath>
</Reference>
<Reference Include="System.IO, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>packages\System.IO.4.3.0\lib\net462\System.IO.dll</HintPath>
</Reference>
<Reference Include="System.IO.Compression, Version=4.1.2.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL">
<HintPath>packages\System.IO.Compression.4.3.0\lib\net46\System.IO.Compression.dll</HintPath>
</Reference>
<Reference Include="System.IO.Compression.FileSystem" />
<Reference Include="System.IO.Compression.ZipFile, Version=4.0.2.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL">
<HintPath>packages\System.IO.Compression.ZipFile.4.3.0\lib\net46\System.IO.Compression.ZipFile.dll</HintPath>
</Reference>
<Reference Include="System.IO.FileSystem, Version=4.0.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>packages\System.IO.FileSystem.4.3.0\lib\net46\System.IO.FileSystem.dll</HintPath>
</Reference>
<Reference Include="System.IO.FileSystem.Primitives, Version=4.0.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>packages\System.IO.FileSystem.Primitives.4.3.0\lib\net46\System.IO.FileSystem.Primitives.dll</HintPath>
</Reference>
<Reference Include="System.Linq, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>packages\System.Linq.4.3.0\lib\net463\System.Linq.dll</HintPath>
</Reference>
<Reference Include="System.Linq.Expressions, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>packages\System.Linq.Expressions.4.3.0\lib\net463\System.Linq.Expressions.dll</HintPath>
</Reference>
<Reference Include="System.Memory, Version=4.0.1.2, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>packages\System.Memory.4.5.5\lib\net461\System.Memory.dll</HintPath>
</Reference>
<Reference Include="System.Net.Http, Version=4.1.1.3, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>packages\System.Net.Http.4.3.4\lib\net46\System.Net.Http.dll</HintPath>
</Reference>
<Reference Include="System.Net.Sockets, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>packages\System.Net.Sockets.4.3.0\lib\net46\System.Net.Sockets.dll</HintPath>
</Reference>
<Reference Include="System.Numerics" />
<Reference Include="System.Numerics.Vectors, Version=4.1.4.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll</HintPath>
</Reference>
<Reference Include="System.Reflection, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>packages\System.Reflection.4.3.0\lib\net462\System.Reflection.dll</HintPath>
</Reference>
<Reference Include="System.Runtime, Version=4.1.1.1, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>packages\System.Runtime.4.3.1\lib\net462\System.Runtime.dll</HintPath>
</Reference>
<Reference Include="System.Runtime.CompilerServices.Unsafe, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>packages\System.Runtime.CompilerServices.Unsafe.6.0.0\lib\net461\System.Runtime.CompilerServices.Unsafe.dll</HintPath>
</Reference>
<Reference Include="System.Runtime.Extensions, Version=4.1.1.1, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>packages\System.Runtime.Extensions.4.3.1\lib\net462\System.Runtime.Extensions.dll</HintPath>
</Reference>
<Reference Include="System.Runtime.InteropServices, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>packages\System.Runtime.InteropServices.4.3.0\lib\net463\System.Runtime.InteropServices.dll</HintPath>
</Reference>
<Reference Include="System.Runtime.InteropServices.RuntimeInformation, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>packages\System.Runtime.InteropServices.RuntimeInformation.4.3.0\lib\net45\System.Runtime.InteropServices.RuntimeInformation.dll</HintPath>
</Reference>
<Reference Include="System.Security.Cryptography.Algorithms, Version=4.2.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>packages\System.Security.Cryptography.Algorithms.4.3.1\lib\net463\System.Security.Cryptography.Algorithms.dll</HintPath>
</Reference>
<Reference Include="System.Security.Cryptography.Encoding, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>packages\System.Security.Cryptography.Encoding.4.3.0\lib\net46\System.Security.Cryptography.Encoding.dll</HintPath>
</Reference>
<Reference Include="System.Security.Cryptography.Primitives, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>packages\System.Security.Cryptography.Primitives.4.3.0\lib\net46\System.Security.Cryptography.Primitives.dll</HintPath>
</Reference>
<Reference Include="System.Security.Cryptography.X509Certificates, Version=4.1.1.2, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>packages\System.Security.Cryptography.X509Certificates.4.3.2\lib\net461\System.Security.Cryptography.X509Certificates.dll</HintPath>
</Reference>
<Reference Include="System.Text.RegularExpressions, Version=4.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>packages\System.Text.RegularExpressions.4.3.1\lib\net463\System.Text.RegularExpressions.dll</HintPath>
</Reference>
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Deployment" />
<Reference Include="System.Drawing" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml" />
<Reference Include="System.Xml.ReaderWriter, Version=4.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>packages\System.Xml.ReaderWriter.4.3.1\lib\net46\System.Xml.ReaderWriter.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="DownloadForm.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="DownloadForm.Designer.cs">
<DependentUpon>DownloadForm.cs</DependentUpon>
</Compile>
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Version.cs" />
<EmbeddedResource Include="DownloadForm.resx">
<DependentUpon>DownloadForm.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
<SubType>Designer</SubType>
</EmbeddedResource>
<Compile Include="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
<None Include="..\..\public\favicon.ico">
<Link>favicon.ico</Link>
</None>
<None Include="packages.config" />
<None Include="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
</None>
<Compile Include="Properties\Settings.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Settings.settings</DependentUpon>
<DesignTimeSharedInput>True</DesignTimeSharedInput>
</Compile>
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
</ItemGroup>
<ItemGroup>
<Content Include=".gitignore" />
<Content Include="app.manifest" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105.The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('packages\Costura.Fody.5.7.0\build\Costura.Fody.props')" Text="$([System.String]::Format('$(ErrorText)', 'packages\Costura.Fody.5.7.0\build\Costura.Fody.props'))" />
<Error Condition="!Exists('packages\Costura.Fody.5.7.0\build\Costura.Fody.targets')" Text="$([System.String]::Format('$(ErrorText)', 'packages\Costura.Fody.5.7.0\build\Costura.Fody.targets'))" />
<Error Condition="!Exists('packages\Fody.6.6.4\build\Fody.targets')" Text="$([System.String]::Format('$(ErrorText)', 'packages\Fody.6.6.4\build\Fody.targets'))" />
<Error Condition="!Exists('packages\NETStandard.Library.2.0.3\build\netstandard2.0\NETStandard.Library.targets')" Text="$([System.String]::Format('$(ErrorText)', 'packages\NETStandard.Library.2.0.3\build\netstandard2.0\NETStandard.Library.targets'))" />
</Target>
<Import Project="packages\Costura.Fody.5.7.0\build\Costura.Fody.targets" Condition="Exists('packages\Costura.Fody.5.7.0\build\Costura.Fody.targets')" />
<Import Project="packages\Fody.6.6.4\build\Fody.targets" Condition="Exists('packages\Fody.6.6.4\build\Fody.targets')" />
<Import Project="packages\NETStandard.Library.2.0.3\build\netstandard2.0\NETStandard.Library.targets" Condition="Exists('packages\NETStandard.Library.2.0.3\build\netstandard2.0\NETStandard.Library.targets')" />
</Project>

@ -0,0 +1,16 @@

Microsoft Visual Studio Solution File, Format Version 12.00
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UptimeKuma", "UptimeKuma.csproj", "{2DB53988-1D93-4AC0-90C4-96ADEAAC5C04}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{2DB53988-1D93-4AC0-90C4-96ADEAAC5C04}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2DB53988-1D93-4AC0-90C4-96ADEAAC5C04}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2DB53988-1D93-4AC0-90C4-96ADEAAC5C04}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2DB53988-1D93-4AC0-90C4-96ADEAAC5C04}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal

@ -0,0 +1,3 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:Boolean x:Key="/Default/ResxEditorPersonal/CheckedGroups/=UptimeKuma_002FProperties_002FResources/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/ResxEditorPersonal/Initialized/@EntryValue">True</s:Boolean></wpf:ResourceDictionary>

@ -0,0 +1,9 @@
namespace UptimeKuma {
public class Version {
public string latest { get; set; }
public string slow { get; set; }
public string beta { get; set; }
public string nodejs { get; set; }
public string exe { get; set; }
}
}

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">
<asmv3:application>
<asmv3:windowsSettings>
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</dpiAware>
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2</dpiAwareness>
</asmv3:windowsSettings>
</asmv3:application>
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
<security>
<requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
<!-- UAC Manifest Options
If you want to change the Windows User Account Control level replace the
requestedExecutionLevel node with one of the following.
<requestedExecutionLevel level="asInvoker" uiAccess="false" />
<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
<requestedExecutionLevel level="highestAvailable" uiAccess="false" />
Specifying requestedExecutionLevel element will disable file and registry virtualization.
Remove this element if your application requires this virtualization for backwards
compatibility.
-->
<requestedExecutionLevel level="asInvoker" uiAccess="false" />
</requestedPrivileges>
</security>
</trustInfo>
</assembly>

@ -0,0 +1,56 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Costura.Fody" version="5.7.0" targetFramework="net472" developmentDependency="true" />
<package id="Fody" version="6.6.4" targetFramework="net472" developmentDependency="true" />
<package id="Microsoft.NETCore.Platforms" version="7.0.0" targetFramework="net472" />
<package id="Microsoft.Win32.Primitives" version="4.3.0" targetFramework="net472" />
<package id="NETStandard.Library" version="2.0.3" targetFramework="net472" />
<package id="Newtonsoft.Json" version="13.0.2" targetFramework="net472" />
<package id="System.AppContext" version="4.3.0" targetFramework="net472" />
<package id="System.Console" version="4.3.1" targetFramework="net472" />
<package id="System.Diagnostics.DiagnosticSource" version="7.0.1" targetFramework="net472" />
<package id="System.Net.Http" version="4.3.4" targetFramework="net472" />
<package id="System.Runtime.Extensions" version="4.3.1" targetFramework="net472" />
<package id="System.Security.Cryptography.Algorithms" version="4.3.1" targetFramework="net472" />
<package id="System.Security.Cryptography.X509Certificates" version="4.3.2" targetFramework="net472" />
<package id="System.Text.RegularExpressions" version="4.3.1" targetFramework="net472" />
<package id="System.Xml.ReaderWriter" version="4.3.1" targetFramework="net472" />
<package id="System.Memory" version="4.5.5" targetFramework="net472" />
<package id="System.Net.Primitives" version="4.3.1" targetFramework="net472" />
<package id="System.Runtime" version="4.3.1" targetFramework="net472" />
<package id="System.Buffers" version="4.5.1" targetFramework="net472" />
<package id="System.Collections" version="4.3.0" targetFramework="net472" />
<package id="System.Collections.Concurrent" version="4.3.0" targetFramework="net472" />
<package id="System.Diagnostics.Debug" version="4.3.0" targetFramework="net472" />
<package id="System.Diagnostics.Tools" version="4.3.0" targetFramework="net472" />
<package id="System.Diagnostics.Tracing" version="4.3.0" targetFramework="net472" />
<package id="System.Globalization" version="4.3.0" targetFramework="net472" />
<package id="System.Globalization.Calendars" version="4.3.0" targetFramework="net472" />
<package id="System.IO" version="4.3.0" targetFramework="net472" />
<package id="System.IO.Compression" version="4.3.0" targetFramework="net472" />
<package id="System.IO.Compression.ZipFile" version="4.3.0" targetFramework="net472" />
<package id="System.IO.FileSystem" version="4.3.0" targetFramework="net472" />
<package id="System.IO.FileSystem.Primitives" version="4.3.0" targetFramework="net472" />
<package id="System.Linq" version="4.3.0" targetFramework="net472" />
<package id="System.Linq.Expressions" version="4.3.0" targetFramework="net472" />
<package id="System.Net.Sockets" version="4.3.0" targetFramework="net472" />
<package id="System.Numerics.Vectors" version="4.5.0" targetFramework="net472" />
<package id="System.ObjectModel" version="4.3.0" targetFramework="net472" />
<package id="System.Reflection" version="4.3.0" targetFramework="net472" />
<package id="System.Reflection.Extensions" version="4.3.0" targetFramework="net472" />
<package id="System.Reflection.Primitives" version="4.3.0" targetFramework="net472" />
<package id="System.Resources.ResourceManager" version="4.3.0" targetFramework="net472" />
<package id="System.Runtime.CompilerServices.Unsafe" version="6.0.0" targetFramework="net472" />
<package id="System.Runtime.Handles" version="4.3.0" targetFramework="net472" />
<package id="System.Runtime.InteropServices" version="4.3.0" targetFramework="net472" />
<package id="System.Runtime.InteropServices.RuntimeInformation" version="4.3.0" targetFramework="net472" />
<package id="System.Runtime.Numerics" version="4.3.0" targetFramework="net472" />
<package id="System.Security.Cryptography.Encoding" version="4.3.0" targetFramework="net472" />
<package id="System.Security.Cryptography.Primitives" version="4.3.0" targetFramework="net472" />
<package id="System.Text.Encoding" version="4.3.0" targetFramework="net472" />
<package id="System.Text.Encoding.Extensions" version="4.3.0" targetFramework="net472" />
<package id="System.Threading" version="4.3.0" targetFramework="net472" />
<package id="System.Threading.Tasks" version="4.3.0" targetFramework="net472" />
<package id="System.Threading.Timer" version="4.3.0" targetFramework="net472" />
<package id="System.Xml.XDocument" version="4.3.0" targetFramework="net472" />
</packages>

@ -1,4 +1,8 @@
/*
* Due to the weird issue in Portainer that the healthcheck script is still pointing to this script for unknown reason.
* IT CANNOT BE DROPPED, even though it looks like it is not used.
* See more: https://github.com/louislam/uptime-kuma/issues/2774#issuecomment-1429092359
*
* Deprecated: Changed to healthcheck.go, it will be deleted in the future.
* This script should be run after a period of time (180s), because the server may need some time to prepare.
*/
@ -19,17 +23,17 @@ if (sslKey && sslCert) {
// If host is omitted, the server will accept connections on the unspecified IPv6 address (::) when IPv6 is available and the unspecified IPv4 address (0.0.0.0) otherwise.
// Dual-stack support for (::)
let hostname = process.env.UPTIME_KUMA_SERVICE_HOST || process.env.UPTIME_KUMA_HOST || "::";
let hostname = process.env.UPTIME_KUMA_HOST;
// Also read HOST if not *BSD, as HOST is a system environment variable in FreeBSD
if (!hostname && !FBSD) {
hostname = process.env.HOST;
}
const port = parseInt(process.env.UPTIME_KUMA_SERVICE_PORT || process.env.UPTIME_KUMA_PORT || process.env.PORT || 3001);
const port = parseInt(process.env.UPTIME_KUMA_PORT || process.env.PORT || 3001);
let options = {
host: hostname,
host: hostname || "127.0.0.1",
port: port,
timeout: 28 * 1000,
};

@ -26,7 +26,8 @@ if (! exists) {
fs.writeFileSync("package.json", JSON.stringify(pkg, null, 4) + "\n");
// Also update package-lock.json
childProcess.spawnSync("npm", [ "install" ]);
const npm = /^win/.test(process.platform) ? "npm.cmd" : "npm";
childProcess.spawnSync(npm, [ "install" ]);
commit(newVersion);
tag(newVersion);

3357
package-lock.json generated

File diff suppressed because it is too large Load Diff

@ -1,6 +1,6 @@
{
"name": "uptime-kuma",
"version": "1.20.0-beta.0",
"version": "1.20.2",
"license": "MIT",
"repository": {
"type": "git",
@ -39,7 +39,7 @@
"build-docker-nightly-amd64": "docker buildx build -f docker/dockerfile --platform linux/amd64 -t louislam/uptime-kuma:nightly-amd64 --target nightly . --push --progress plain",
"build-docker-pr-test": "docker buildx build -f docker/dockerfile --platform linux/amd64,linux/arm64 -t louislam/uptime-kuma:pr-test --target pr-test . --push",
"upload-artifacts": "docker buildx build -f docker/dockerfile --platform linux/amd64 -t louislam/uptime-kuma:upload-artifact --build-arg VERSION --build-arg GITHUB_TOKEN --target upload-artifact . --progress plain",
"setup": "git checkout 1.19.6 && npm ci --production && npm run download-dist",
"setup": "git checkout 1.20.2 && npm ci --production && npm run download-dist",
"download-dist": "node extra/download-dist.js",
"mark-as-nightly": "node extra/mark-as-nightly.js",
"reset-password": "node extra/reset-password.js",
@ -63,7 +63,8 @@
"cy:run": "npx cypress run --browser chrome --headless --config-file ./config/cypress.config.js",
"cy:run:unit": "npx cypress run --browser chrome --headless --config-file ./config/cypress.frontend.config.js",
"cypress-open": "concurrently -k -r \"node test/prepare-test-server.js && node server/server.js --port=3002 --data-dir=./data/test/\" \"cypress open --config-file ./config/cypress.config.js\"",
"build-healthcheck-armv7": "cross-env GOOS=linux GOARCH=arm GOARM=7 go build -x -o ./extra/healthcheck-armv7 ./extra/healthcheck.go"
"build-healthcheck-armv7": "cross-env GOOS=linux GOARCH=arm GOARM=7 go build -x -o ./extra/healthcheck-armv7 ./extra/healthcheck.go",
"depoly-demo-server": "node extra/deploy-demo-server.js"
},
"dependencies": {
"@grpc/grpc-js": "~1.7.3",
@ -98,10 +99,11 @@
"jsonwebtoken": "~9.0.0",
"jwt-decode": "~3.1.2",
"limiter": "~2.1.0",
"mongodb": "~4.13.0",
"mongodb": "~4.14.0",
"mqtt": "~4.3.7",
"mssql": "~8.1.4",
"mysql2": "~2.3.3",
"nanoid": "^3.3.4",
"node-cloudflared-tunnel": "~1.0.9",
"node-radius-client": "~1.0.0",
"nodemailer": "~6.6.5",
@ -112,6 +114,7 @@
"prom-client": "~13.2.0",
"prometheus-api-metrics": "~3.2.1",
"protobufjs": "~7.1.1",
"qs": "~6.10.4",
"redbean-node": "~0.2.0",
"redis": "~4.5.1",
"socket.io": "~4.5.3",
@ -150,8 +153,9 @@
"eslint": "~8.14.0",
"eslint-plugin-vue": "~8.7.1",
"favico.js": "~0.3.10",
"marked": "~4.2.5",
"jest": "~27.2.5",
"marked": "~4.2.5",
"node-ssh": "~13.0.1",
"postcss-html": "~1.5.0",
"postcss-rtlcss": "~3.7.2",
"postcss-scss": "~4.0.4",

@ -2,7 +2,9 @@ const basicAuth = require("express-basic-auth");
const passwordHash = require("./password-hash");
const { R } = require("redbean-node");
const { setting } = require("./util-server");
const { loginRateLimiter } = require("./rate-limiter");
const { loginRateLimiter, apiRateLimiter } = require("./rate-limiter");
const { Settings } = require("./settings");
const dayjs = require("dayjs");
/**
* Login to web app
@ -34,8 +36,36 @@ exports.login = async function (username, password) {
};
/**
* Callback for myAuthorizer
* @callback myAuthorizerCB
* Validate a provided API key
* @param {string} key API key to verify
*/
async function verifyAPIKey(key) {
if (typeof key !== "string") {
return false;
}
// uk prefix + key ID is before _
let index = key.substring(2, key.indexOf("_"));
let clear = key.substring(key.indexOf("_") + 1, key.length);
let hash = await R.findOne("api_key", " id=? ", [ index ]);
if (hash === null) {
return false;
}
let current = dayjs();
let expiry = dayjs(hash.expires);
if (expiry.diff(current) < 0 || !hash.active) {
return false;
}
return hash && passwordHash.verify(clear, hash.key);
}
/**
* Callback for basic auth authorizers
* @callback authCallback
* @param {any} err Any error encountered
* @param {boolean} authorized Is the client authorized?
*/
@ -44,9 +74,31 @@ exports.login = async function (username, password) {
* Custom authorizer for express-basic-auth
* @param {string} username
* @param {string} password
* @param {myAuthorizerCB} callback
* @param {authCallback} callback
*/
function apiAuthorizer(username, password, callback) {
// API Rate Limit
apiRateLimiter.pass(null, 0).then((pass) => {
if (pass) {
verifyAPIKey(password).then((valid) => {
callback(null, valid);
// Only allow a set number of api requests per minute
// (currently set to 60)
apiRateLimiter.removeTokens(1);
});
} else {
callback(null, false);
}
});
}
/**
* Custom authorizer for express-basic-auth
* @param {string} username
* @param {string} password
* @param {authCallback} callback
*/
function myAuthorizer(username, password, callback) {
function userAuthorizer(username, password, callback) {
// Login Rate Limit
loginRateLimiter.pass(null, 0).then((pass) => {
if (pass) {
@ -71,7 +123,7 @@ function myAuthorizer(username, password, callback) {
*/
exports.basicAuth = async function (req, res, next) {
const middleware = basicAuth({
authorizer: myAuthorizer,
authorizer: userAuthorizer,
authorizeAsync: true,
challenge: true,
});
@ -84,3 +136,32 @@ exports.basicAuth = async function (req, res, next) {
next();
}
};
/**
* Use use API Key if API keys enabled, else use basic auth
* @param {express.Request} req Express request object
* @param {express.Response} res Express response object
* @param {express.NextFunction} next
*/
exports.apiAuth = async function (req, res, next) {
if (!await Settings.get("disableAuth")) {
let usingAPIKeys = await Settings.get("apiKeysEnabled");
let middleware;
if (usingAPIKeys) {
middleware = basicAuth({
authorizer: apiAuthorizer,
authorizeAsync: true,
challenge: true,
});
} else {
middleware = basicAuth({
authorizer: userAuthorizer,
authorizeAsync: true,
challenge: true,
});
}
middleware(req, res, next);
} else {
next();
}
};

@ -113,6 +113,31 @@ async function sendProxyList(socket) {
return list;
}
/**
* Emit API key list to client
* @param {Socket} socket Socket.io socket instance
* @returns {Promise<void>}
*/
async function sendAPIKeyList(socket) {
const timeLogger = new TimeLogger();
let result = [];
const list = await R.find(
"api_key",
"user_id=?",
[ socket.userID ],
);
for (let bean of list) {
result.push(bean.toPublicJSON());
}
io.to(socket.userID).emit("apiKeyList", result);
timeLogger.print("Sent API Key List");
return list;
}
/**
* Emits the version information to the client.
* @param {Socket} socket Socket.io socket instance
@ -157,6 +182,7 @@ module.exports = {
sendImportantHeartbeatList,
sendHeartbeatList,
sendProxyList,
sendAPIKeyList,
sendInfo,
sendDockerHostList
};

@ -70,6 +70,9 @@ class Database {
"patch-maintenance-table2.sql": true,
"patch-add-gamedig-monitor.sql": true,
"patch-add-google-analytics-status-page-tag.sql": true,
"patch-http-body-encoding.sql": true,
"patch-add-description-monitor.sql": true,
"patch-api-key-table.sql": true,
};
/**
@ -496,6 +499,16 @@ class Database {
const shmPath = Database.path + "-shm";
const walPath = Database.path + "-wal";
// Make sure we have a backup to restore before deleting old db
if (
!fs.existsSync(this.backupPath)
&& !fs.existsSync(shmPath)
&& !fs.existsSync(walPath)
) {
log.error("db", "Backup file not found! Leaving database in failed state.");
process.exit(1);
}
// Delete patch failed db
try {
if (fs.existsSync(Database.path)) {

@ -0,0 +1,76 @@
const { BeanModel } = require("redbean-node/dist/bean-model");
const { R } = require("redbean-node");
const dayjs = require("dayjs");
class APIKey extends BeanModel {
/**
* Get the current status of this API key
* @returns {string} active, inactive or expired
*/
getStatus() {
let current = dayjs();
let expiry = dayjs(this.expires);
if (expiry.diff(current) < 0) {
return "expired";
}
return this.active ? "active" : "inactive";
}
/**
* Returns an object that ready to parse to JSON
* @returns {Object}
*/
toJSON() {
return {
id: this.id,
key: this.key,
name: this.name,
userID: this.user_id,
createdDate: this.created_date,
active: this.active,
expires: this.expires,
status: this.getStatus(),
};
}
/**
* Returns an object that ready to parse to JSON with sensitive fields
* removed
* @returns {Object}
*/
toPublicJSON() {
return {
id: this.id,
name: this.name,
userID: this.user_id,
createdDate: this.created_date,
active: this.active,
expires: this.expires,
status: this.getStatus(),
};
}
/**
* Create a new API Key and store it in the database
* @param {Object} key Object sent by client
* @param {int} userID ID of socket user
* @returns {Promise<bean>}
*/
static async save(key, userID) {
let bean;
bean = R.dispense("api_key");
bean.key = key.key;
bean.name = key.name;
bean.user_id = userID;
bean.active = key.active;
bean.expires = key.expires;
await R.store(bean);
return bean;
}
}
module.exports = APIKey;

@ -72,6 +72,7 @@ class Monitor extends BeanModel {
let data = {
id: this.id,
name: this.name,
description: this.description,
url: this.url,
method: this.method,
hostname: this.hostname,
@ -111,6 +112,7 @@ class Monitor extends BeanModel {
radiusCalledStationId: this.radiusCalledStationId,
radiusCallingStationId: this.radiusCallingStationId,
game: this.game,
httpBodyEncoding: this.httpBodyEncoding
};
if (includeSensitiveData) {
@ -143,7 +145,7 @@ class Monitor extends BeanModel {
* @returns {Promise<LooseObject<any>[]>}
*/
async getTags() {
return await R.getAll("SELECT mt.*, tag.name, tag.color FROM monitor_tag mt JOIN tag ON mt.tag_id = tag.id WHERE mt.monitor_id = ?", [ this.id ]);
return await R.getAll("SELECT mt.*, tag.name, tag.color FROM monitor_tag mt JOIN tag ON mt.tag_id = tag.id WHERE mt.monitor_id = ? ORDER BY tag.name", [ this.id ]);
}
/**
@ -203,7 +205,7 @@ class Monitor extends BeanModel {
let previousBeat = null;
let retries = 0;
let prometheus = new Prometheus(this);
this.prometheus = new Prometheus(this);
const beat = async () => {
@ -272,17 +274,34 @@ class Monitor extends BeanModel {
log.debug("monitor", `[${this.name}] Prepare Options for axios`);
let contentType = null;
let bodyValue = null;
if (this.body && (typeof this.body === "string" && this.body.trim().length > 0)) {
if (!this.httpBodyEncoding || this.httpBodyEncoding === "json") {
try {
bodyValue = JSON.parse(this.body);
contentType = "application/json";
} catch (e) {
throw new Error("Your JSON body is invalid. " + e.message);
}
} else if (this.httpBodyEncoding === "xml") {
bodyValue = this.body;
contentType = "text/xml; charset=utf-8";
}
}
// Axios Options
const options = {
url: this.url,
method: (this.method || "get").toLowerCase(),
...(this.body ? { data: JSON.parse(this.body) } : {}),
timeout: this.interval * 1000 * 0.8,
headers: {
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9",
"User-Agent": "Uptime-Kuma/" + version,
...(this.headers ? JSON.parse(this.headers) : {}),
...(contentType ? { "Content-Type": contentType } : {}),
...(basicAuthHeader),
...(this.headers ? JSON.parse(this.headers) : {})
},
maxRedirects: this.maxredirects,
validateStatus: (status) => {
@ -290,6 +309,10 @@ class Monitor extends BeanModel {
},
};
if (bodyValue) {
options.data = bodyValue;
}
if (this.proxy_id) {
const proxy = await R.load("proxy", this.proxy_id);
@ -755,7 +778,7 @@ class Monitor extends BeanModel {
await R.store(bean);
log.debug("monitor", `[${this.name}] prometheus.update`);
prometheus.update(bean, tlsInfo);
this.prometheus?.update(bean, tlsInfo);
previousBeat = bean;
@ -840,15 +863,15 @@ class Monitor extends BeanModel {
clearTimeout(this.heartbeatInterval);
this.isStop = true;
this.prometheus().remove();
this.prometheus?.remove();
}
/**
* Get a new prometheus instance
* @returns {Prometheus}
* Get prometheus instance
* @returns {Prometheus|undefined}
*/
prometheus() {
return new Prometheus(this);
getPrometheus() {
return this.prometheus;
}
/**

@ -60,8 +60,11 @@ class StatusPage extends BeanModel {
}
// OG Meta Tags
head.append(`<meta property="og:title" content="${statusPage.title}" />`);
head.append(`<meta property="og:description" content="${description155}" />`);
let ogTitle = $("<meta property=\"og:title\" content=\"\" />").attr("content", statusPage.title);
head.append(ogTitle);
let ogDescription = $("<meta property=\"og:description\" content=\"\" />").attr("content", description155);
head.append(ogDescription);
// Preload data
// Add jsesc, fix https://github.com/louislam/uptime-kuma/issues/2186

@ -42,7 +42,7 @@ class Slack extends NotificationProvider {
const time = heartbeatJSON["time"];
const textMsg = "Uptime Kuma Alert";
let data = {
"text": monitorJSON ? textMsg + `: ${monitorJSON.name}` : textMsg,
"text": `${textMsg}\n${msg}`,
"channel": notification.slackchannel,
"username": notification.slackusername,
"icon_emoji": notification.slackiconemo,

@ -9,11 +9,18 @@ class Telegram extends NotificationProvider {
let okMsg = "Sent Successfully.";
try {
let params = {
chat_id: notification.telegramChatID,
text: msg,
disable_notification: notification.telegramSendSilently ?? false,
protect_content: notification.telegramProtectContent ?? false,
};
if (notification.telegramMessageThreadID) {
params.message_thread_id = notification.telegramMessageThreadID;
}
await axios.get(`https://api.telegram.org/bot${notification.telegramBotToken}/sendMessage`, {
params: {
chat_id: notification.telegramChatID,
text: msg,
},
params: params,
});
return okMsg;

@ -54,6 +54,13 @@ const loginRateLimiter = new KumaRateLimiter({
errorMessage: "Too frequently, try again later."
});
const apiRateLimiter = new KumaRateLimiter({
tokensPerInterval: 60,
interval: "minute",
fireImmediately: true,
errorMessage: "Too frequently, try again later."
});
const twoFaRateLimiter = new KumaRateLimiter({
tokensPerInterval: 30,
interval: "minute",
@ -63,5 +70,6 @@ const twoFaRateLimiter = new KumaRateLimiter({
module.exports = {
loginRateLimiter,
apiRateLimiter,
twoFaRateLimiter,
};

@ -1,5 +1,5 @@
let express = require("express");
const { allowDevAllOrigin, allowAllOrigin, percentageToColor, filterAndJoin, send403 } = require("../util-server");
const { allowDevAllOrigin, allowAllOrigin, percentageToColor, filterAndJoin, sendHttpError } = require("../util-server");
const { R } = require("redbean-node");
const apicache = require("../modules/apicache");
const Monitor = require("../model/monitor");
@ -175,7 +175,7 @@ router.get("/api/badge/:id/status", cache("5 minutes"), async (request, response
response.type("image/svg+xml");
response.send(svg);
} catch (error) {
send403(response, error.message);
sendHttpError(response, error.message);
}
});
@ -242,7 +242,7 @@ router.get("/api/badge/:id/uptime/:duration?", cache("5 minutes"), async (reques
response.type("image/svg+xml");
response.send(svg);
} catch (error) {
send403(response, error.message);
sendHttpError(response, error.message);
}
});
@ -303,7 +303,7 @@ router.get("/api/badge/:id/ping/:duration?", cache("5 minutes"), async (request,
response.type("image/svg+xml");
response.send(svg);
} catch (error) {
send403(response, error.message);
sendHttpError(response, error.message);
}
});
@ -373,7 +373,7 @@ router.get("/api/badge/:id/avg-response/:duration?", cache("5 minutes"), async (
response.type("image/svg+xml");
response.send(svg);
} catch (error) {
send403(response, error.message);
sendHttpError(response, error.message);
}
});
@ -464,7 +464,7 @@ router.get("/api/badge/:id/cert-exp", cache("5 minutes"), async (request, respon
response.type("image/svg+xml");
response.send(svg);
} catch (error) {
send403(response, error.message);
sendHttpError(response, error.message);
}
});
@ -536,7 +536,7 @@ router.get("/api/badge/:id/response", cache("5 minutes"), async (request, respon
response.type("image/svg+xml");
response.send(svg);
} catch (error) {
send403(response, error.message);
sendHttpError(response, error.message);
}
});

@ -2,7 +2,7 @@ let express = require("express");
const apicache = require("../modules/apicache");
const { UptimeKumaServer } = require("../uptime-kuma-server");
const StatusPage = require("../model/status_page");
const { allowDevAllOrigin, send403 } = require("../util-server");
const { allowDevAllOrigin, sendHttpError } = require("../util-server");
const { R } = require("redbean-node");
const Monitor = require("../model/monitor");
@ -44,10 +44,7 @@ router.get("/api/status-page/:slug", cache("5 minutes"), async (request, respons
let statusPageData = await StatusPage.getStatusPageData(statusPage);
if (!statusPageData) {
response.statusCode = 404;
response.json({
msg: "Not Found"
});
sendHttpError(response, "Not Found");
return;
}
@ -55,7 +52,7 @@ router.get("/api/status-page/:slug", cache("5 minutes"), async (request, respons
response.json(statusPageData);
} catch (error) {
send403(response, error.message);
sendHttpError(response, error.message);
}
});
@ -103,7 +100,7 @@ router.get("/api/status-page/heartbeat/:slug", cache("1 minutes"), async (reques
});
} catch (error) {
send403(response, error.message);
sendHttpError(response, error.message);
}
});
@ -119,10 +116,7 @@ router.get("/api/status-page/:slug/manifest.json", cache("1440 minutes"), async
]);
if (!statusPage) {
response.statusCode = 404;
response.json({
msg: "Not Found"
});
sendHttpError(response, "Not Found");
return;
}
@ -141,7 +135,7 @@ router.get("/api/status-page/:slug/manifest.json", cache("1440 minutes"), async
});
} catch (error) {
send403(response, error.message);
sendHttpError(response, error.message);
}
});

@ -87,7 +87,7 @@ log.debug("server", "Importing Background Jobs");
const { initBackgroundJobs, stopBackgroundJobs } = require("./jobs");
const { loginRateLimiter, twoFaRateLimiter } = require("./rate-limiter");
const { basicAuth } = require("./auth");
const { apiAuth } = require("./auth");
const { login } = require("./auth");
const passwordHash = require("./password-hash");
@ -129,7 +129,7 @@ if (config.demoMode) {
}
// Must be after io instantiation
const { sendNotificationList, sendHeartbeatList, sendImportantHeartbeatList, sendInfo, sendProxyList, sendDockerHostList } = require("./client");
const { sendNotificationList, sendHeartbeatList, sendImportantHeartbeatList, sendInfo, sendProxyList, sendDockerHostList, sendAPIKeyList } = require("./client");
const { statusPageSocketHandler } = require("./socket-handlers/status-page-socket-handler");
const databaseSocketHandler = require("./socket-handlers/database-socket-handler");
const TwoFA = require("./2fa");
@ -138,6 +138,7 @@ const { cloudflaredSocketHandler, autoStart: cloudflaredAutoStart, stop: cloudfl
const { proxySocketHandler } = require("./socket-handlers/proxy-socket-handler");
const { dockerSocketHandler } = require("./socket-handlers/docker-socket-handler");
const { maintenanceSocketHandler } = require("./socket-handlers/maintenance-socket-handler");
const { apiKeySocketHandler } = require("./socket-handlers/api-key-socket-handler");
const { generalSocketHandler } = require("./socket-handlers/general-socket-handler");
const { Settings } = require("./settings");
const { CacheableDnsHttpAgent } = require("./cacheable-dns-http-agent");
@ -229,7 +230,7 @@ let needSetup = false;
// Prometheus API metrics /metrics
// With Basic Auth using the first user's username/password
app.get("/metrics", basicAuth, prometheusAPIMetrics());
app.get("/metrics", apiAuth, prometheusAPIMetrics());
app.use("/", expressStaticGzip("dist", {
enableBrotli: true,
@ -677,10 +678,8 @@ let needSetup = false;
throw new Error("Permission denied.");
}
// Reset Prometheus labels
server.monitorList[monitor.id]?.prometheus()?.remove();
bean.name = monitor.name;
bean.description = monitor.description;
bean.type = monitor.type;
bean.url = monitor.url;
bean.method = monitor.method;
@ -729,6 +728,7 @@ let needSetup = false;
bean.radiusCalledStationId = monitor.radiusCalledStationId;
bean.radiusCallingStationId = monitor.radiusCallingStationId;
bean.radiusSecret = monitor.radiusSecret;
bean.httpBodyEncoding = monitor.httpBodyEncoding;
bean.validate();
@ -1320,6 +1320,7 @@ let needSetup = false;
let monitor = {
// Define the new variable from earlier here
name: monitorListData[i].name,
description: monitorListData[i].description,
type: monitorListData[i].type,
url: monitorListData[i].url,
method: monitorListData[i].method || "GET",
@ -1503,6 +1504,7 @@ let needSetup = false;
proxySocketHandler(socket);
dockerSocketHandler(socket);
maintenanceSocketHandler(socket);
apiKeySocketHandler(socket);
generalSocketHandler(socket, server);
pluginsHandler(socket, server);
@ -1611,6 +1613,7 @@ async function afterLogin(socket, user) {
sendNotificationList(socket);
sendProxyList(socket);
sendDockerHostList(socket);
sendAPIKeyList(socket);
await sleep(500);

@ -0,0 +1,150 @@
const { checkLogin } = require("../util-server");
const { log } = require("../../src/util");
const { R } = require("redbean-node");
const { nanoid } = require("nanoid");
const passwordHash = require("../password-hash");
const apicache = require("../modules/apicache");
const APIKey = require("../model/api_key");
const { Settings } = require("../settings");
const { sendAPIKeyList } = require("../client");
/**
* Handlers for Maintenance
* @param {Socket} socket Socket.io instance
*/
module.exports.apiKeySocketHandler = (socket) => {
// Add a new api key
socket.on("addAPIKey", async (key, callback) => {
try {
checkLogin(socket);
let clearKey = nanoid(40);
let hashedKey = passwordHash.generate(clearKey);
key["key"] = hashedKey;
let bean = await APIKey.save(key, socket.userID);
log.debug("apikeys", "Added API Key");
log.debug("apikeys", key);
// Append key ID and prefix to start of key seperated by _, used to get
// correct hash when validating key.
let formattedKey = "uk" + bean.id + "_" + clearKey;
await sendAPIKeyList(socket);
// Enable API auth if the user creates a key, otherwise only basic
// auth will be used for API.
await Settings.set("apiKeysEnabled", true);
callback({
ok: true,
msg: "Added Successfully.",
key: formattedKey,
keyID: bean.id,
});
} catch (e) {
callback({
ok: false,
msg: e.message,
});
}
});
socket.on("getAPIKeyList", async (callback) => {
try {
checkLogin(socket);
await sendAPIKeyList(socket);
callback({
ok: true,
});
} catch (e) {
console.error(e);
callback({
ok: false,
msg: e.message,
});
}
});
socket.on("deleteAPIKey", async (keyID, callback) => {
try {
checkLogin(socket);
log.debug("apikeys", `Deleted API Key: ${keyID} User ID: ${socket.userID}`);
await R.exec("DELETE FROM api_key WHERE id = ? AND user_id = ? ", [
keyID,
socket.userID,
]);
apicache.clear();
callback({
ok: true,
msg: "Deleted Successfully.",
});
await sendAPIKeyList(socket);
} catch (e) {
callback({
ok: false,
msg: e.message,
});
}
});
socket.on("disableAPIKey", async (keyID, callback) => {
try {
checkLogin(socket);
log.debug("apikeys", `Disabled Key: ${keyID} User ID: ${socket.userID}`);
await R.exec("UPDATE api_key SET active = 0 WHERE id = ? ", [
keyID,
]);
apicache.clear();
callback({
ok: true,
msg: "Disabled Successfully.",
});
await sendAPIKeyList(socket);
} catch (e) {
callback({
ok: false,
msg: e.message,
});
}
});
socket.on("enableAPIKey", async (keyID, callback) => {
try {
checkLogin(socket);
log.debug("apikeys", `Enabled Key: ${keyID} User ID: ${socket.userID}`);
await R.exec("UPDATE api_key SET active = 1 WHERE id = ? ", [
keyID,
]);
apicache.clear();
callback({
ok: true,
msg: "Enabled Successfully",
});
await sendAPIKeyList(socket);
} catch (e) {
callback({
ok: false,
msg: e.message,
});
}
});
};

@ -9,10 +9,10 @@ let gameList = null;
/**
* Get a game list via GameDig
* @returns {any[]}
* @returns {Object[]} list of games supported by GameDig
*/
function getGameList() {
if (!gameList) {
if (gameList == null) {
gameList = gameResolver._readGames().games.sort((a, b) => {
if ( a.pretty < b.pretty ) {
return -1;
@ -22,9 +22,8 @@ function getGameList() {
}
return 0;
});
} else {
return gameList;
}
return gameList;
}
module.exports.generalSocketHandler = (socket, server) => {

@ -292,14 +292,23 @@ exports.postgresQuery = function (connectionString, query) {
client.end();
} else {
// Connected here
client.query(query, (err, res) => {
if (err) {
reject(err);
} else {
resolve(res);
try {
// No query provided by user, use SELECT 1
if (!query || (typeof query === "string" && query.trim() === "")) {
query = "SELECT 1";
}
client.end();
});
client.query(query, (err, res) => {
if (err) {
reject(err);
} else {
resolve(res);
}
client.end();
});
} catch (e) {
reject(e);
}
}
});
@ -323,7 +332,7 @@ exports.mysqlQuery = function (connectionString, query) {
reject(err);
})
.finally(() => {
connection.end();
connection.destroy();
});
});
};
@ -730,15 +739,27 @@ exports.filterAndJoin = (parts, connector = "") => {
};
/**
* Send a 403 response
* Send an Error response
* @param {Object} res Express response object
* @param {string} [msg=""] Message to send
*/
module.exports.send403 = (res, msg = "") => {
res.status(403).json({
"status": "fail",
"msg": msg,
});
module.exports.sendHttpError = (res, msg = "") => {
if (msg.includes("SQLITE_BUSY") || msg.includes("SQLITE_LOCKED")) {
res.status(503).json({
"status": "fail",
"msg": msg,
});
} else if (msg.toLowerCase().includes("not found")) {
res.status(404).json({
"status": "fail",
"msg": msg,
});
} else {
res.status(403).json({
"status": "fail",
"msg": msg,
});
}
};
function timeObjectConvertTimezone(obj, timezone, timeObjectToUTC = true) {

@ -0,0 +1,219 @@
<template>
<form @submit.prevent="submit">
<div ref="keyaddmodal" class="modal fade" tabindex="-1" data-bs-backdrop="static">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">
{{ $t("Add API Key") }}
</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close" />
</div>
<div class="modal-body">
<!-- Name -->
<div class="mb-3">
<label for="name" class="form-label">{{ $t("Name") }}</label>
<input
id="name" v-model="key.name" type="text" class="form-control"
required
>
</div>
<!-- Expiry -->
<div class="my-3">
<label class="form-label">{{ $t("Expiry date") }}</label>
<div class="d-flex flex-row align-items-center">
<div class="col-6">
<Datepicker
v-model="key.expires"
:dark="$root.isDark"
:monthChangeOnScroll="false"
:minDate="minDate"
format="yyyy-MM-dd HH:mm"
modelType="yyyy-MM-dd HH:mm:ss"
:required="!noExpire"
:disabled="noExpire"
/>
</div>
<div class="col-6 ms-3">
<div class="form-check mb-0">
<input
id="no-expire" v-model="noExpire" class="form-check-input"
type="checkbox"
>
<label class="form-check-label" for="no-expire">{{
$t("Don't expire")
}}</label>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<button
id="monitor-submit-btn" class="btn btn-primary" type="submit"
:disabled="processing"
>
{{ $t("Generate") }}
</button>
</div>
</div>
</div>
</div>
</div>
<div ref="keymodal" class="modal fade" tabindex="-1" data-bs-backdrop="static">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">
{{ $t("Key Added") }}
</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close" />
</div>
<div class="modal-body">
<div class="mb-3">
{{ $t("apiKeyAddedMsg") }}
</div>
<div class="mb-3">
<CopyableInput v-model="clearKey" disabled="disabled" />
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-primary" data-bs-dismiss="modal">
{{ $t('Continue') }}
</button>
</div>
</div>
</div>
</div>
</form>
</template>
<script lang="ts">
import { Modal } from "bootstrap";
import { useToast } from "vue-toastification";
import dayjs from "dayjs";
import Datepicker from "@vuepic/vue-datepicker";
import CopyableInput from "./CopyableInput.vue";
const toast = useToast();
export default {
components: {
CopyableInput,
Datepicker
},
props: {},
// emits: [ "added" ],
data() {
return {
keyaddmodal: null,
keymodal: null,
processing: false,
key: {},
dark: (this.$root.theme === "dark"),
minDate: this.$root.date(dayjs()) + " 00:00",
clearKey: null,
noExpire: false,
};
},
mounted() {
this.keyaddmodal = new Modal(this.$refs.keyaddmodal);
this.keymodal = new Modal(this.$refs.keymodal);
},
methods: {
/**
* Show modal
*/
show() {
this.id = null;
this.key = {
name: "",
expires: this.minDate,
active: 1,
};
this.keyaddmodal.show();
},
/** Submit data to server */
async submit() {
this.processing = true;
if (this.noExpire) {
this.key.expires = null;
}
this.$root.addAPIKey(this.key, async (res) => {
this.keyaddmodal.hide();
this.processing = false;
if (res.ok) {
this.clearKey = res.key;
this.keymodal.show();
this.clearForm();
} else {
toast.error(res.msg);
}
});
},
}
};
</script>
<style lang="scss" scoped>
@import "../assets/vars.scss";
.dark {
.modal-dialog .form-text, .modal-dialog p {
color: $dark-font-color;
}
}
.shadow-box {
padding: 20px;
}
textarea {
min-height: 150px;
}
.dark-calendar::-webkit-calendar-picker-indicator {
filter: invert(1);
}
.weekday-picker {
display: flex;
gap: 10px;
& > div {
display: flex;
flex-direction: column;
align-items: center;
width: 40px;
.form-check-inline {
margin-right: 0;
}
}
}
.day-picker {
display: flex;
gap: 10px;
flex-wrap: wrap;
& > div {
display: flex;
flex-direction: column;
align-items: center;
width: 40px;
.form-check-inline {
margin-right: 0;
}
}
}
</style>

@ -4,7 +4,7 @@
<div class="modal-content">
<div class="modal-header">
<h5 id="exampleModalLabel" class="modal-title">
{{ $t("Confirm") }}
{{ title || $t("Confirm") }}
</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close" />
</div>
@ -15,7 +15,7 @@
<button type="button" class="btn" :class="btnStyle" data-bs-dismiss="modal" @click="yes">
{{ yesText }}
</button>
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal" @click="no">
{{ noText }}
</button>
</div>
@ -44,8 +44,13 @@ export default {
type: String,
default: "No",
},
/** Title to show on modal. Defaults to translated version of "Config" */
title: {
type: String,
default: null,
}
},
emits: [ "yes" ],
emits: [ "yes", "no" ],
data: () => ({
modal: null,
}),
@ -63,6 +68,12 @@ export default {
yes() {
this.$emit("yes");
},
/**
* @emits string "no" Notify the parent when No is pressed
*/
no() {
this.$emit("no");
}
},
};
</script>

@ -19,7 +19,7 @@
{{ $t("No Monitors, please") }} <router-link to="/add">{{ $t("add one") }}</router-link>
</div>
<router-link v-for="(item, index) in sortedMonitorList" :key="index" :to="monitorURL(item.id)" class="item" :class="{ 'disabled': ! item.active }">
<router-link v-for="(item, index) in sortedMonitorList" :key="index" :to="monitorURL(item.id)" class="item" :class="{ 'disabled': ! item.active }" :title="item.description">
<div class="row">
<div class="col-9 col-md-8 small-padding" :class="{ 'monitor-item': $root.userHeartbeatBar == 'bottom' || $root.userHeartbeatBar == 'none' }">
<div class="info">

@ -13,7 +13,10 @@
<div class="mb-3">
<label for="notification-type" class="form-label">{{ $t("Notification Type") }}</label>
<select id="notification-type" v-model="notification.type" class="form-select">
<option v-for="type in notificationTypes" :key="type" :value="type">{{ $t(type) }}</option>
<option v-for="(name, type) in notificationNameList.regularList" :key="type" :value="type">{{ name }}</option>
<optgroup :label="$t('notificationRegional')">
<option v-for="(name, type) in notificationNameList.regionalList" :key="type" :value="type">{{ name }}</option>
</optgroup>
</select>
</div>
@ -67,7 +70,7 @@
</Confirm>
</template>
<script lang="ts">
<script>
import { Modal } from "bootstrap";
import Confirm from "./Confirm.vue";
@ -103,7 +106,91 @@ export default {
return null;
}
return NotificationFormList[this.notification.type];
}
},
notificationNameList() {
let regularList = {
"alerta": "Alerta",
"AlertNow": "AlertNow",
"apprise": this.$t("apprise"),
"Bark": "Bark",
"clicksendsms": "ClickSend SMS",
"discord": "Discord",
"GoogleChat": "Google Chat (Google Workspace)",
"gorush": "Gorush",
"gotify": "Gotify",
"HomeAssistant": "Home Assistant",
"Kook": "Kook",
"line": "LINE Messenger",
"LineNotify": "LINE Notify",
"lunasea": "LunaSea",
"matrix": "Matrix",
"mattermost": "Mattermost",
"ntfy": "Ntfy",
"octopush": "Octopush",
"OneBot": "OneBot",
"PagerDuty": "PagerDuty",
"pushbullet": "Pushbullet",
"PushByTechulus": "Push by Techulus",
"pushover": "Pushover",
"pushy": "Pushy",
"rocket.chat": "Rocket.Chat",
"signal": "Signal",
"slack": "Slack",
"squadcast": "SquadCast",
"SMSEagle": "SMSEagle",
"smtp": this.$t("smtp"),
"stackfield": "Stackfield",
"teams": "Microsoft Teams",
"telegram": "Telegram",
"Splunk": "Splunk",
"webhook": "Webhook",
"GoAlert": "GoAlert",
"ZohoCliq": "ZohoCliq"
};
// Put notifications here if it's not supported in most regions or its documentation is not in English
let regionalList = {
"AliyunSMS": "AliyunSMS (阿里云短信服务)",
"DingDing": "DingDing (钉钉自定义机器人)",
"Feishu": "Feishu (飞书)",
"FreeMobile": "FreeMobile (mobile.free.fr)",
"PushDeer": "PushDeer",
"promosms": "PromoSMS",
"serwersms": "SerwerSMS.pl",
"SMSManager": "SmsManager (smsmanager.cz)",
"WeCom": "WeCom (企业微信群机器人)",
"ServerChan": "ServerChan (Server酱)",
};
// Sort by notification name
// No idea how, but it works
// https://stackoverflow.com/questions/1069666/sorting-object-property-by-values
let sort = (list2) => {
return Object.entries(list2)
.sort(([ , a ], [ , b ]) => a.localeCompare(b))
.reduce((r, [ k, v ]) => ({
...r,
[k]: v
}), {});
};
return {
regularList: sort(regularList),
regionalList: sort(regionalList),
};
},
notificationFullNameList() {
let list = {};
for (let [ key, value ] of Object.entries(this.notificationNameList.regularList)) {
list[key] = value;
}
for (let [ key, value ] of Object.entries(this.notificationNameList.regionalList)) {
list[key] = value;
}
return list;
},
},
watch: {
@ -203,11 +290,12 @@ export default {
* @return {string}
*/
getUniqueDefaultName(notificationKey) {
let index = 1;
let name = "";
do {
name = this.$t("defaultNotificationName", {
notification: this.$t(notificationKey).replace(/\(.+\)/, "").trim(),
notification: this.notificationFullNameList[notificationKey].replace(/\(.+\)/, "").trim(),
number: index++
});
} while (this.$root.notificationList.find(it => it.name === name));

@ -18,9 +18,15 @@
</template>
<script>
/**
* @typedef {import('./TagsManager.vue').Tag} Tag
*/
export default {
props: {
/** Object representing tag */
/** Object representing tag
* @type {Tag}
*/
item: {
type: Object,
required: true,
@ -32,7 +38,7 @@ export default {
},
/**
* Size of tag
* @values normal, small
* @type {"normal" | "small"}
*/
size: {
type: String,

@ -12,7 +12,17 @@
<div class="modal-body">
<div class="mb-3">
<label for="tag-name" class="form-label">{{ $t("Name") }}</label>
<input id="tag-name" v-model="tag.name" type="text" class="form-control" required>
<input
id="tag-name"
v-model="tag.name"
type="text"
class="form-control"
:class="{'is-invalid': nameInvalid}"
required
>
<div class="invalid-feedback">
{{ $t("Tag with this name already exist.") }}
</div>
</div>
<div class="mb-3">
@ -112,7 +122,11 @@ export default {
updated: {
type: Function,
default: () => {},
}
},
existingTags: {
type: Array,
default: () => [],
},
},
data() {
return {
@ -132,6 +146,7 @@ export default {
removingMonitor: [],
addingMonitor: [],
selectedAddMonitor: null,
nameInvalid: false,
};
},
@ -160,11 +175,16 @@ export default {
watch: {
// Set color option to "Custom" when a unknown color is entered
"tag.color"(to, from) {
if (colorOptions(this).find(x => x.color === to) == null) {
if (to !== "" && colorOptions(this).find(x => x.color === to) == null) {
this.selectedColor.name = this.$t("Custom");
this.selectedColor.color = to;
}
},
"tag.name"(to, from) {
if (to != null) {
this.validate();
}
},
selectedColor(to, from) {
if (to != null) {
this.tag.color = to.color;
@ -197,6 +217,35 @@ export default {
this.$refs.confirmDelete.show();
},
/**
* Reset the editTag form
*/
reset() {
this.selectedColor = null;
this.tag = {
id: null,
name: "",
color: "",
};
this.monitors = [];
this.removingMonitor = [];
this.addingMonitor = [];
},
/**
* Check for existing tags of the same name, set invalid input
* @returns {boolean} True if editing tag is valid
*/
validate() {
this.nameInvalid = false;
const sameName = this.existingTags.find((existingTag) => existingTag.name === this.tag.name);
if (sameName != null && sameName.id !== this.tag.id) {
this.nameInvalid = true;
return false;
}
return true;
},
/**
* Load tag information for display in the edit dialog
* @param {Object} tag tag object to edit
@ -228,6 +277,27 @@ export default {
this.processing = true;
let editResult = true;
if (!this.validate()) {
this.processing = false;
return;
}
if (this.tag.id == null) {
await this.addTagAsync(this.tag).then((res) => {
if (!res.ok) {
this.$root.toastRes(res.msg);
editResult = false;
} else {
this.tag.id = res.tag.id;
this.updated();
}
});
}
if (!editResult) {
return;
}
for (let addId of this.addingMonitor) {
await this.addMonitorTagAsync(this.tag.id, addId, "").then((res) => {
if (!res.ok) {
@ -263,9 +333,9 @@ export default {
* Delete the editing tag from server
* @returns {void}
*/
deleteTag() {
async deleteTag() {
this.processing = true;
this.$root.getSocket().emit("deleteTag", this.tag.id, (res) => {
await this.deleteTagAsync(this.tag.id).then((res) => {
this.$root.toastRes(res);
this.processing = false;
@ -309,6 +379,28 @@ export default {
return getMonitorRelativeURL(id);
},
/**
* Add a tag asynchronously
* @param {Object} newTag Object representing new tag to add
* @returns {Promise<void>}
*/
addTagAsync(newTag) {
return new Promise((resolve) => {
this.$root.getSocket().emit("addTag", newTag, resolve);
});
},
/**
* Delete a tag asynchronously
* @param {number} tagId ID of tag to delete
* @returns {Promise<void>}
*/
deleteTagAsync(tagId) {
return new Promise((resolve) => {
this.$root.getSocket().emit("deleteTag", tagId, resolve);
});
},
/**
* Add a tag to a monitor asynchronously
* @param {number} tagId ID of tag to add

@ -134,13 +134,27 @@ import { colorOptions } from "../util-frontend";
import Tag from "../components/Tag.vue";
const toast = useToast();
/**
* @typedef Tag
* @type {object}
* @property {number | undefined} id
* @property {number | undefined} monitor_id
* @property {number | undefined} tag_id
* @property {string} value
* @property {string} name
* @property {string} color
* @property {boolean | undefined} new
*/
export default {
components: {
Tag,
VueMultiselect,
},
props: {
/** Array of tags to be pre-selected */
/** Array of tags to be pre-selected
* @type {Tag[]}
*/
preSelectedTags: {
type: Array,
default: () => [],
@ -148,10 +162,14 @@ export default {
},
data() {
return {
/** @type {Modal | null} */
modal: null,
/** @type {Tag[]} */
existingTags: [],
processing: false,
/** @type {Tag[]} */
newTags: [],
/** @type {Tag[]} */
deleteTags: [],
newDraftTag: {
name: null,

@ -16,7 +16,7 @@
<div class="mb-3">
<label for="gorush-platform" class="form-label">{{ $t("Platform") }}</label><span style="color: red;"><sup>*</sup></span>
<select id="gorush-platform" v-model="$parent.notification.gorushPlatform" class="form-select">
<option value="ios">{{ $t("iOS") }}</option>
<option value="ios">iOS</option>
<option value="android">{{ $t("Android") }}</option>
<option value="huawei">{{ $t("Huawei") }}</option>
</select>

@ -28,6 +28,30 @@
<a :href="telegramGetUpdatesURL('withToken')" target="_blank" style="word-break: break-word;">{{ telegramGetUpdatesURL("masked") }}</a>
</p>
</div>
<label for="message_thread_id" class="form-label">{{ $t("telegramMessageThreadID") }}</label>
<input id="message_thread_id" v-model="$parent.notification.telegramMessageThreadID" type="text" class="form-control">
<p class="form-text">{{ $t("telegramMessageThreadIDDescription") }}</p>
<div class="form-check form-switch">
<input v-model="$parent.notification.telegramSendSilently" class="form-check-input" type="checkbox">
<label class="form-check-label">{{ $t("telegramSendSilently") }}</label>
</div>
<div class="form-text">
{{ $t("telegramSendSilentlyDescription") }}
</div>
</div>
<div class="mb-3">
<div class="form-check form-switch">
<input v-model="$parent.notification.telegramProtectContent" class="form-check-input" type="checkbox">
<label class="form-check-label">{{ $t("telegramProtectContent") }}</label>
</div>
<div class="form-text">
{{ $t("telegramProtectContentDescription") }}
</div>
</div>
</template>

@ -0,0 +1,257 @@
<template>
<div>
<div class="add-btn">
<button class="btn btn-primary me-2" type="button" @click="$refs.apiKeyDialog.show()">
<font-awesome-icon icon="plus" /> {{ $t("Add API Key") }}
</button>
</div>
<div>
<span v-if="Object.keys(keyList).length === 0" class="d-flex align-items-center justify-content-center my-3">
{{ $t("No API Keys") }}
</span>
<div
v-for="(item, index) in keyList"
:key="index"
class="item"
:class="item.status"
>
<div class="left-part">
<div
class="circle"
></div>
<div class="info">
<div class="title">{{ item.name }}</div>
<div class="status">
{{ $t("apiKey-" + item.status) }}
</div>
<div class="date">
{{ $t("Created") }}: {{ item.createdDate }}
</div>
<div class="date">
{{ $t("Expires") }}: {{ item.expires || $t("Never") }}
</div>
</div>
</div>
<div class="buttons">
<div class="btn-group" role="group">
<button v-if="item.active" class="btn btn-normal" @click="disableDialog(item.id)">
<font-awesome-icon icon="pause" /> {{ $t("Disable") }}
</button>
<button v-if="!item.active" class="btn btn-primary" @click="enableKey(item.id)">
<font-awesome-icon icon="play" /> {{ $t("Enable") }}
</button>
<button class="btn btn-danger" @click="deleteDialog(item.id)">
<font-awesome-icon icon="trash" /> {{ $t("Delete") }}
</button>
</div>
</div>
</div>
</div>
<div class="text-center mt-3" style="font-size: 13px;">
<a href="https://github.com/louislam/uptime-kuma/wiki/API-Keys" target="_blank">{{ $t("Learn More") }}</a>
</div>
<Confirm ref="confirmPause" :yes-text="$t('Yes')" :no-text="$t('No')" @yes="disableKey">
{{ $t("disableAPIKeyMsg") }}
</Confirm>
<Confirm ref="confirmDelete" btn-style="btn-danger" :yes-text="$t('Yes')" :no-text="$t('No')" @yes="deleteKey">
{{ $t("deleteAPIKeyMsg") }}
</Confirm>
<APIKeyDialog ref="apiKeyDialog" />
</div>
</template>
<script>
import APIKeyDialog from "../../components/APIKeyDialog.vue";
import Confirm from "../Confirm.vue";
import { useToast } from "vue-toastification";
const toast = useToast();
export default {
components: {
APIKeyDialog,
Confirm,
},
data() {
return {
selectedKeyID: null,
};
},
computed: {
keyList() {
let result = Object.values(this.$root.apiKeyList);
return result;
},
},
methods: {
/**
* Show dialog to confirm deletion
* @param {number} keyID ID of monitor that is being deleted
*/
deleteDialog(keyID) {
this.selectedKeyID = keyID;
this.$refs.confirmDelete.show();
},
/**
* Delete a key
*/
deleteKey() {
this.$root.deleteAPIKey(this.selectedKeyID, (res) => {
if (res.ok) {
toast.success(res.msg);
} else {
toast.error(res.msg);
}
});
},
/**
* Show dialog to confirm pause
*/
disableDialog(keyID) {
this.selectedKeyID = keyID;
this.$refs.confirmPause.show();
},
/**
* Pause maintenance
*/
disableKey() {
this.$root.getSocket().emit("disableAPIKey", this.selectedKeyID, (res) => {
this.$root.toastRes(res);
});
},
/**
* Resume maintenance
*/
enableKey(id) {
this.$root.getSocket().emit("enableAPIKey", id, (res) => {
this.$root.toastRes(res);
});
},
},
};
</script>
<style lang="scss" scoped>
@import "../../assets/vars.scss";
.mobile {
.item {
flex-direction: column;
align-items: flex-start;
margin-bottom: 20px;
}
}
.add-btn {
padding-top: 20px;
padding-bottom: 20px;
}
.item {
display: flex;
align-items: center;
gap: 10px;
text-decoration: none;
border-radius: 10px;
transition: all ease-in-out 0.15s;
justify-content: space-between;
padding: 10px;
min-height: 90px;
margin-bottom: 5px;
&:hover {
background-color: $highlight-white;
}
&.active {
.circle {
background-color: $primary;
}
}
&.inactive {
.circle {
background-color: $danger;
}
}
&.expired {
.left-part {
opacity: 0.3;
}
.circle {
background-color: $dark-font-color;
}
}
.left-part {
display: flex;
gap: 12px;
align-items: center;
.circle {
width: 25px;
height: 25px;
border-radius: 50rem;
}
.info {
.title {
font-weight: bold;
font-size: 20px;
}
.status {
font-size: 14px;
}
}
}
.buttons {
display: flex;
gap: 8px;
flex-direction: row-reverse;
.btn-group {
width: 310px;
}
}
}
.date {
margin-top: 5px;
display: block;
font-size: 14px;
background-color: rgba(255, 255, 255, 0.5);
border-radius: 20px;
padding: 0 10px;
width: fit-content;
.dark & {
color: white;
background-color: rgba(255, 255, 255, 0.1);
}
}
.dark {
.item {
&:hover {
background-color: $dark-bg2;
}
}
}
</style>

@ -1,5 +1,9 @@
<template>
<div>
<div class="my-4">
<div class="mx-4 pt-1 my-3">
<button class="btn btn-primary" @click.stop="addTag"><font-awesome-icon icon="plus" /> {{ $t("Add New Tag") }}</button>
</div>
<div class="tags-list my-3">
<div v-for="(tag, index) in tagsList" :key="tag.id" class="d-flex align-items-center mx-4 py-1 tags-list-row" :disabled="processing" @click="editTag(index)">
<div class="col-5 ps-1">
@ -19,7 +23,7 @@
</div>
</div>
<TagEditDialog ref="tagEditDialog" :updated="tagsUpdated" />
<TagEditDialog ref="tagEditDialog" :updated="tagsUpdated" :existing-tags="tagsList" />
<Confirm ref="confirmDelete" btn-style="btn-danger" :yes-text="$t('Yes')" :no-text="$t('No')" @yes="deleteTag">
{{ $t("confirmDeleteTagMsg") }}
</Confirm>
@ -100,6 +104,15 @@ export default {
this.$refs.confirmDelete.show();
},
/**
* Show dialog for adding a new tag
* @returns {void}
*/
addTag() {
this.$refs.tagEditDialog.reset();
this.$refs.tagEditDialog.show();
},
/**
* Show dialog for editing a tag
* @param {number} index index of the tag to edit in the local tagsList
@ -149,10 +162,10 @@ export default {
.tags-list .tags-list-row {
cursor: pointer;
border-bottom: 1px solid rgba(0, 0, 0, 0.125);
border-top: 1px solid rgba(0, 0, 0, 0.125);
.dark & {
border-bottom: 1px solid $dark-border-color;
border-top: 1px solid $dark-border-color;
}
&:hover {
@ -164,8 +177,4 @@ export default {
}
}
.tags-list .tags-list-row:last-child {
border: none;
}
</style>

@ -15,6 +15,7 @@ const languageList = {
"fa": "Farsi",
"pt-PT": "Português (Portugal)",
"pt-BR": "Português (Brasileiro)",
"fi": "Suomi",
"fr-FR": "Français (France)",
"hu": "Magyar",
"hr-HR": "Hrvatski",

@ -3,6 +3,9 @@ import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome";
// Add Free Font Awesome Icons
// https://fontawesome.com/v5.15/icons?d=gallery&p=2&s=solid&m=free
// In order to add an icon, you have to:
// 1) add the icon name in the import statement below;
// 2) add the icon name to the library.add() statement below.
import {
faArrowAltCircleUp,
faCog,
@ -45,6 +48,7 @@ import {
faHeartbeat,
faFilter,
faInfoCircle,
faClone,
} from "@fortawesome/free-solid-svg-icons";
library.add(
@ -90,6 +94,7 @@ library.add(
faHeartbeat,
faFilter,
faInfoCircle,
faClone,
);
export { FontAwesomeIcon };

@ -90,7 +90,7 @@
"Heartbeat Interval": "فاصل نبضات القلب",
"Retries": "يحاول مجدداً",
"Heartbeat Retry Interval": "الفاصل الزمني لإعادة محاكمة نبضات القلب",
"Resend Notification if Down X times consequently": "إعادة تقديم الإخطار إذا انخفض x مرات بالتالي",
"Resend Notification if Down X times consecutively": "إعادة تقديم الإخطار إذا انخفض x مرات بالتالي",
"Advanced": "متقدم",
"Upside Down Mode": "وضع أسفل أسفل",
"Max. Redirects": "الأعلى. إعادة التوجيه",
@ -215,6 +215,7 @@
"Bot Token": "رمز الروبوت",
"wayToGetTelegramToken": "يمكنك الحصول على رمز من {0}.",
"Chat ID": "معرف الدردشة",
"telegramMessageThreadID": "معرف المواضيع",
"supportTelegramChatID": "دعم الدردشة المباشرة / معرف الدردشة للقناة",
"wayToGetTelegramChatID": "يمكنك الحصول على معرف الدردشة الخاص بك عن طريق إرسال رسالة إلى الروبوت والانتقال إلى عنوان URL هذا لعرض Chat_id",
"YOUR BOT TOKEN HERE": "رمز الروبوت الخاص بك هنا",

@ -227,7 +227,7 @@
"smtpCC": "Явно копие до имейл адрес:",
"smtpBCC": "Скрито копие до имейл адрес:",
"Discord Webhook URL": "Discord URL адрес на уеб кука",
"wayToGetDiscordURL": "Може да създадете, от меню \"Настройки на сървъра\" -> \"Интеграции\" -> \"Уеб куки\" -> \"Нова уеб кука\"",
"wayToGetDiscordURL": "Можете да създадете, от меню \"Настройки на сървъра\" -> \"Интеграции\" -> \"Уеб куки\" -> \"Нова уеб кука\"",
"Bot Display Name": "Име на бота, което да се показва",
"Prefix Custom Message": "Модифицирано обръщение",
"Hello @everyone is...": "Здравейте, {'@'}everyone е…",
@ -236,8 +236,8 @@
"Number": "Номер",
"Recipients": "Получатели",
"needSignalAPI": "Необходимо е да разполагате със Signal клиент с REST API.",
"wayToCheckSignalURL": "Може да посетите този URL адрес, ако се нуждаете от помощ при настройването:",
"signalImportant": "ВАЖНО: Не може да смесвате \"Групи\" и \"Номера\" в поле \"Получатели\"!",
"wayToCheckSignalURL": "Можете да посетите този URL адрес, ако се нуждаете от помощ при настройването:",
"signalImportant": "ВАЖНО: Не можете да смесвате \"Групи\" и \"Номера\" в поле \"Получатели\"!",
"Application Token": "Токен код за приложението",
"Server URL": "URL адрес на сървъра",
"Priority": "Приоритет",
@ -278,21 +278,21 @@
"Basic Settings": "Основни настройки",
"User ID": "Потребител ID",
"Messaging API": "API за съобщаване",
"wayToGetLineChannelToken": "Необходимо е първо да посетите {0}, за да създадете (Messaging API) за доставчик и канал, след което може да вземете токен кода за канал и потребителско ID от споменатите по-горе елементи на менюто.",
"wayToGetLineChannelToken": "Необходимо е първо да посетите {0}, за да създадете (Messaging API) за доставчик и канал, след което можете да вземете токен кода за канал и потребителско ID от споменатите по-горе елементи на менюто.",
"Icon URL": "URL адрес за иконка",
"aboutIconURL": "Може да предоставите линк към картинка в поле \"URL Адрес за иконка\" за да отмените картинката на профила по подразбиране. Няма да се използва, ако вече сте настроили емотикон.",
"aboutMattermostChannelName": "Може да замените канала по подразбиране, към който публикува уеб куката, като въведете името на канала в полето \"Канал име\". Трябва да бъде активирано в настройките за уеб кука на Mattermost. Например: #other-channel",
"aboutIconURL": "Можете да предоставите линк към картинка в поле \"URL Адрес за иконка\" за да отмените картинката на профила по подразбиране. Няма да се използва, ако вече сте настроили емотикон.",
"aboutMattermostChannelName": "Можете да замените канала по подразбиране, към който публикува уеб куката, като въведете името на канала в полето \"Канал име\". Трябва да бъде активирано в настройките за уеб кука на Mattermost. Например: #other-channel",
"matrix": "Matrix",
"promosmsTypeEco": "SMS ECO - евтин, но бавен. Често е претоварен. Само за получатели от Полша.",
"promosmsTypeFlash": "SMS FLASH - Съобщението автоматично се показва на устройството на получателя. Само за получатели от Полша.",
"promosmsTypeFull": "SMS FULL - Високо ниво на SMS услуга. Може да използвате Вашето име като подател (Необходимо е първо да регистрирате името). Надежден метод за съобщения тип тревога.",
"promosmsTypeFull": "SMS FULL - Високо ниво на SMS услуга. Можете да използвате Вашето име като подател (Необходимо е първо да регистрирате името). Надежден метод за съобщения тип тревога.",
"promosmsTypeSpeed": "SMS SPEED - Най-висок приоритет в системата. Много бърза и надеждна, но същевременно скъпа услуга. (Около два пъти по-висока цена в сравнение с SMS FULL).",
"promosmsPhoneNumber": "Телефонен номер (за получатели от Полша, може да пропуснете въвеждането на код за населено място)",
"promosmsPhoneNumber": "Телефонен номер (за получатели от Полша, можете да пропуснете въвеждането на код за населено място)",
"promosmsSMSSender": "SMS Подател име: Предварително регистрирано име или някое от имената по подразбиране: InfoSMS, SMS Info, MaxSMS, INFO, SMS",
"Feishu WebHookUrl": "Feishu URL адрес за уеб кука",
"matrixHomeserverURL": "Сървър URL адрес (започва с http(s):// и порт по желание)",
"Internal Room Id": "ID на вътрешна стая",
"matrixDesc1": "Може да намерите \"ID на вътрешна стая\" в разширените настройки на стаята във вашия Matrix клиент. Примерен изглед: !QMdRCpUIfLwsfjxye6:home.server.",
"matrixDesc1": "Можете да намерите \"ID на вътрешна стая\" в разширените настройки на стаята във вашия Matrix клиент. Примерен изглед: !QMdRCpUIfLwsfjxye6:home.server.",
"matrixDesc2": "Силно препоръчваме да създадете НОВ потребител и да НЕ използвате токен кодът на вашия личен Matrix потребител, т.к. той позволява пълен достъп до вашия акаунт и всички стаи към които сте се присъединили. Вместо това създайте нов потребител и го поканете само в стаята, където желаете да получавате известията. Токен код за достъп ще получите изпълнявайки {0}",
"Method": "Метод",
"Body": "Съобщение",
@ -304,7 +304,7 @@
"clearDataOlderThan": "Ще се съхранява за {0} дни.",
"records": "записа",
"One record": "Един запис",
"steamApiKeyDescription": "За да мониторирате Steam Gameserver се нуждаете от Steam Web-API ключ. Може да регистрирате Вашия API ключ тук: ",
"steamApiKeyDescription": "За да мониторирате Steam Game Server се нуждаете от Steam Web-API ключ. Можете да регистрирате Вашия API ключ тук: ",
"clicksendsms": "ClickSend SMS",
"apiCredentials": "API удостоверяване",
"PasswordsDoNotMatch": "Паролите не съвпадат.",
@ -379,8 +379,8 @@
"setAsDefault": "Зададен по подразбиране",
"deleteProxyMsg": "Сигурни ли сте, че желаете да изтриете това прокси за всички монитори?",
"proxyDescription": "За да функционират трябва да бъдат зададени към монитор.",
"enableProxyDescription": "Това прокси няма да има ефект върху заявките за мониторинг, докато не бъде активирано. Може да контролирате временното деактивиране на проксито от всички монитори чрез статуса на активиране.",
"setAsDefaultProxyDescription": "Това прокси ще бъде активно по подразбиране за новите монитори. Може да го изключите по отделно за всеки един монитор.",
"enableProxyDescription": "Това прокси няма да има ефект върху заявките за мониторинг, докато не бъде активирано. Можете да контролирате временното деактивиране на проксито от всички монитори чрез статуса на активиране.",
"setAsDefaultProxyDescription": "Това прокси ще бъде активно по подразбиране за новите монитори. Можете да го изключвате отделно за всеки един монитор.",
"Certificate Chain": "Верига на сертификата",
"Valid": "Валиден",
"Invalid": "Невалиден",
@ -435,7 +435,7 @@
"cloudflareWebsite": "Cloudflare уеб сайт",
"Message:": "Съобщение:",
"Don't know how to get the token? Please read the guide:": "Не знаете как да вземете токен? Моля, прочетете ръководството:",
"The current connection may be lost if you are currently connecting via Cloudflare Tunnel. Are you sure want to stop it? Type your current password to confirm it.": "Текущата връзка може да прекъсне ако в момента сте свързани чрез \"Cloudflare Tunnel\". Сигурни ли сте, че желаете да го спрете? Въведете Вашата текуща парола за да потвърдите.",
"The current connection may be lost if you are currently connecting via Cloudflare Tunnel. Are you sure want to stop it? Type your current password to confirm it.": "Текущата връзка може да прекъсне ако в момента сте свързани чрез \"Cloudflare Tunnel\". Сигурни ли сте, че желаете да го спрете? Моля, въведете Вашата текуща парола за да потвърдите.",
"Other Software": "Друг софтуер",
"For example: nginx, Apache and Traefik.": "Например: Nginx, Apache и Traefik.",
"Please read": "Моля, прочетете",
@ -513,15 +513,15 @@
"Most likely causes:": "Най-вероятни причини:",
"The resource is no longer available.": "Ресурсът вече не е наличен.",
"There might be a typing error in the address.": "Възможно е да е допусната грешка при изписването на адреса.",
"What you can try:": "Може да опитате:",
"What you can try:": "Какво можете да опитате:",
"Retype the address.": "Повторно въвеждане на адреса.",
"Go back to the previous page.": "Да се върнете към предишната страница.",
"Coming Soon": "Очаквайте скоро",
"wayToGetClickSendSMSToken": "Може да получите API потребителско име и API ключ от {0} .",
"dnsPortDescription": "DNS порт на сървъра. По подразбиране е 53, но може да бъде променен по всяко време.",
"wayToGetClickSendSMSToken": "Можете да получите API потребителско име и API ключ от {0} .",
"dnsPortDescription": "DNS порт на сървъра. По подразбиране е 53. Можете да го промените по всяко време.",
"error": "грешка",
"critical": "критично",
"wayToGetPagerDutyKey": "Може да го получите като посетите Service -> Service Directory -> (Select a service) -> Integrations -> Add integration. Тук трябва да потърсите \"Events API V2\". Повече информация {0}",
"wayToGetPagerDutyKey": "Можете да го получите като посетите Service -> Service Directory -> (Select a service) -> Integrations -> Add integration. Тук трябва да потърсите \"Events API V2\". Повече информация {0}",
"Integration Key": "Ключ за интегриране",
"Integration URL": "URL адрес за интеграция",
"Auto resolve or acknowledged": "Автоматично разрешаване или потвърждаване",
@ -536,10 +536,10 @@
"Domain": "Домейн",
"Workstation": "Работна станция",
"disableCloudflaredNoAuthMsg": "Тъй като сте в режим \"No Auth mode\", парола не се изисква.",
"wayToGetLineNotifyToken": "Може да получите токен код за достъп от {0}",
"wayToGetLineNotifyToken": "Можете да получите токен код за достъп от {0}",
"resendEveryXTimes": "Изпращай повторно на всеки {0} пъти",
"resendDisabled": "Повторното изпращане е изключено",
"Resend Notification if Down X times consequently": "Повторно изпращане на известие, ако е недостъпен X пъти последователно",
"Resend Notification if Down X times consecutively": "Повторно изпращане на известие, ако е недостъпен X пъти последователно",
"Bark Group": "Bark група",
"Bark Sound": "Bark звук",
"HTTP Headers": "HTTP хедъри",
@ -601,7 +601,7 @@
"SMSManager API Docs": "SMSManager API Документация ",
"Gateway Type": "Тип на шлюза",
"SMSManager": "SMSManager",
"You can divide numbers with": "Може да разделяте числата с",
"You can divide numbers with": "Можете да разделяте числата с",
"or": "или",
"recurringInterval": "Интервал",
"Recurring": "Повтаряне",
@ -676,7 +676,7 @@
"wayToGetKookGuildID": "Превключете в 'Developer Mode' в 'Kook' настройките, след което десен клик върху 'guild' за да вземете неговото 'ID'",
"Guild ID": "Guild ID",
"Help": "Помощ",
"Game": "игрови",
"Game": "Игра",
"Custom": "Потребителски",
"infiniteRetention": "Задайте стойност 0 за безкрайно съхранение.",
"Monitor": "Монитор | Монитори",
@ -691,5 +691,10 @@
"installing": "Инсталиране",
"uninstall": "Деинсталирай",
"uninstalling": "Деинсталиране",
"confirmUninstallPlugin": "Сигурни ли сте, че желаете да деинсталирате този плъгин?"
"confirmUninstallPlugin": "Сигурни ли сте, че желаете да деинсталирате този плъгин?",
"markdownSupported": "Поддържа се Markdown синтаксис",
"Google Analytics ID": "Google Analytics ID",
"Edit Tag": "Редактиране на таг",
"Learn More": "Научете повече",
"Server Address": "Сървър адрес"
}

@ -90,7 +90,7 @@
"Heartbeat Interval": "Heartbeat interval",
"Retries": "Počet pokusů",
"Heartbeat Retry Interval": "Interval opakování heartbeatu",
"Resend Notification if Down X times consequently": "Znovu zaslat oznámení, pokud je služba nedostupná Xkrát za sebou",
"Resend Notification if Down X times consecutively": "Zaslat oznámení znovu, pokud je služba nedostupná Xkrát za sebou",
"Advanced": "Rozšířené",
"Upside Down Mode": "Inverzní režim",
"Max. Redirects": "Max. přesměrování",
@ -212,7 +212,7 @@
"Required": "Vyžadováno",
"telegram": "Telegram",
"ZohoCliq": "ZohoCliq",
"Bot Token": "Token robota",
"Bot Token": "Token bota",
"wayToGetTelegramToken": "Token můžete získat od {0}.",
"Chat ID": "ID chatu",
"supportTelegramChatID": "Podpora přímého chatu / skupiny / ID chatu kanálu",
@ -237,7 +237,7 @@
"smtpBCC": "Skrytá kopie",
"discord": "Discord",
"Discord Webhook URL": "URL Webhooku Discord",
"wayToGetDiscordURL": "Získáte tak, že přejdete do Nastavení serveru - > Integrace - > Vytvořit Webhook",
"wayToGetDiscordURL": "Získáte tak, že přejdete do Nastavení serveru - > Integrace - > Zobrazi webhooky -> Nový webhook",
"Bot Display Name": "Zobrazované jméno robota",
"Prefix Custom Message": "Předpona vlastní zprávy",
"Hello @everyone is...": "Dobrý den, {'@'}všichni jsou…",
@ -332,7 +332,7 @@
"Body": "Tělo",
"Headers": "Hlavičky",
"PushUrl": "Push URL",
"HeadersInvalidFormat": "Hlaviča žádosti není platný JSON: ",
"HeadersInvalidFormat": "Hlavičky žádosti nejsou platný JSON: ",
"BodyInvalidFormat": "Text žádosti není platný JSON: ",
"Monitor History": "Historie dohledu",
"clearDataOlderThan": "Historie dohledu bude uchovávána po dobu {0} dní.",
@ -674,7 +674,7 @@
"Proto Content": "Proto obsah",
"Economy": "Úsporná",
"Lowcost": "Nízkonákladová",
"high": "high",
"high": "vysoká",
"General Monitor Type": "Obecný typ dohledu",
"Passive Monitor Type": "Pasivní typ dohledu",
"Specific Monitor Type": "Konkrétní typ dohledu",
@ -691,5 +691,10 @@
"installing": "Instaluji",
"uninstall": "Odinstalace",
"uninstalling": "Odinstalování",
"Packet Size": "Velikost paketu"
"Packet Size": "Velikost paketu",
"markdownSupported": "Markdown syntaxe podporována",
"Google Analytics ID": "ID Google Analytics",
"Edit Tag": "Upravit štítek",
"Server Address": "Adresa serveru",
"Learn More": "Zjistěte více"
}

@ -29,7 +29,7 @@
"Delete": "Slet",
"Current": "Aktuelt",
"Uptime": "Oppetid",
"Cert Exp.": "Certifikatets udløb",
"Cert Exp.": "Certifikatets udløb.",
"day": "Dag | Dage",
"-day": "-Dage",
"hour": "Timer",
@ -350,5 +350,99 @@
"serwersmsAPIUser": "API Brugernavn (inkl. webapi_ prefix)",
"serwersmsAPIPassword": "API Adgangskode",
"serwersmsPhoneNumber": "Telefonnummer",
"serwersmsSenderName": "SMS Afsender Navn (registreret via kundeportal)"
"serwersmsSenderName": "SMS Afsender Navn (registreret via kundeportal)",
"statusMaintenance": "Vedligeholdelse",
"Maintenance": "Vedligeholdelse",
"No Maintenance": "Ingen vedligeholdelse",
"Examples": "Eksempler",
"High": "Høj",
"Recipient Number": "Modtager Nummer",
"From Name/Number": "Fra Navn/Nummer",
"Help": "Hjælp",
"Please use this option carefully!": "Brug venligst denne funktion med forsigtighed!",
"disableauth.message1": "Er du sikker på, at du vil <strong>deaktivere authentication</strong>?",
"successMessage": "Succesmeddelelse",
"error": "fejl",
"critical": "kritisk",
"Customize": "Tilpas",
"Custom Footer": "Brugerdefineret Footer",
"Custom CSS": "Brugerdefineret CSS",
"deleteStatusPageMsg": "Er du sikker på, at du vil slette denne statusside?",
"Proxies": "Proxies",
"default": "Standard",
"enabled": "Aktiveret",
"setAsDefault": "Indstil som standard",
"Certificate Chain": "Certificate Chain",
"Days Remaining:": "Dage tilbage:",
"No status pages": "Ingen statussider",
"Proxy": "Proxy",
"default: notify all devices": "standard: underretter alle enheder",
"Automations can optionally be triggered in Home Assistant:": "Automatiseringer kan valgfrit udløses i Home Assistant:",
"Trigger type:": "Trigger type:",
"Event type:": "Event type:",
"Event data:": "Event data:",
"Frontend Version": "Frontend Version",
"or": "eller",
"Notification Service": "Notifikationstjeneste",
"Domain": "Domæne",
"Google Analytics ID": "Google Analytics ID",
"Edit Tag": "Ændre Tag",
"Learn More": "Lær mere",
"Schedule maintenance": "Planlæg vedligeholdelse",
"Invalid": "Ugyldig",
"User": "Bruger",
"Installed": "Installeret",
"Not installed": "Ikke installeret",
"Running": "Køre",
"Not running": "Køre ikke",
"Remove Token": "Fjern Token",
"Start": "Start",
"Stop": "Stop",
"Add New Status Page": "Tilføj ny statusside",
"Next": "Næste",
"No Proxy": "Ingen proxy",
"New Status Page": "Ny statusside",
"Page Not Found": "Side blev ikke fundet",
"Reverse Proxy": "Reverse Proxy",
"Backup": "Backup",
"About": "Om",
"cloudflareWebsite": "Cloudflare hjemmeside",
"Message:": "Besked:",
"HTTP Headers": "HTTP Headers",
"Trust Proxy": "Trust Proxy",
"For example: nginx, Apache and Traefik.": "For eksempel: nginx, Apache og Traefik.",
"Please read": "Læs venligst",
"Show Powered By": "Vis Powered By",
"Domain Names": "Domænenavne",
"signedInDisp": "Logget ind som {0}",
"Certificate Expiry Notification": "Meddelelse om udløbsdato for certifikatet",
"API Username": "API Brugernavn",
"API Key": "API Key",
"Steam Game Server": "Steam Game Server",
"What you can try:": "Hvad du kan prøve:",
"Go back to the previous page.": "Gå tilbage til forrige side.",
"Coming Soon": "Kommer snart",
"settingsCertificateExpiry": "Udløb af TLS-certifikat",
"Setup Docker Host": "Opsæt Docker Host",
"Connection Type": "Forbindelsestype",
"Docker Daemon": "Docker Daemon",
"socket": "Socket",
"tcp": "TCP / HTTP",
"Docker Container": "Docker Container",
"Container Name / ID": "Container Navn / ID",
"Packet Size": "Pakke størrelse",
"Home Assistant URL": "Home Assistant URL",
"Frontend Version do not match backend version!": "Frontend versionen stemmer ikke overens med backend versionen!",
"Optional": "Valgfri",
"HomeAssistant": "Home Assistant",
"disableauth.message2": "Den er beregnet til scenarier <strong>hvor du har tænkt dig at implementere tredjepartsgodkendelse</strong> foran Uptime Kuma, f.eks. Cloudflare Access, Authelia eller andre godkendelsesmekanismer.",
"deleteProxyMsg": "Er du sikker på, at du vil slette denne proxy for alle monitors?",
"Valid": "Gyldig",
"Don't know how to get the token? Please read the guide:": "Ved du ikke, hvordan du får fat i din Token? Læs venligst guiden:",
"Subject:": "Emne:",
"Footer Text": "Footer tekst",
"Using a Reverse Proxy?": "Bruger du en Reverse Proxy?",
"deleteDockerHostMsg": "Er du sikker på, at du vil slette denne docker host for alle monitors?",
"Docker Host": "Docker Host",
"Docker Hosts": "Docker Hosts"
}

@ -165,7 +165,7 @@
"Pink": "Pink",
"Search...": "Suchen…",
"Heartbeat Retry Interval": "Überprüfungsintervall",
"Resend Notification if Down X times consequently": "Benachrichtigung erneut senden, wenn Inaktiv X mal hintereinander",
"Resend Notification if Down X times consecutively": "Benachrichtigung erneut senden, wenn Inaktiv X mal hintereinander",
"retryCheckEverySecond": "Alle {0} Sekunden neu versuchen",
"resendEveryXTimes": "Erneut versenden alle {0} mal",
"resendDisabled": "Erneut versenden deaktiviert",

@ -135,7 +135,7 @@
"Options": "Optionen",
"confirmImportMsg": "Möchtest du das Backup wirklich importieren? Bitte stelle sicher, dass die richtige Import-Option ausgewählt ist.",
"Keep both": "Beide behalten",
"twoFAVerifyLabel": "Bitte trage deinen Token ein, um zu verifizieren, dass 2FA funktioniert",
"twoFAVerifyLabel": "Bitte trage deinen Token ein, um zu verifizieren, dass 2FA funktioniert:",
"Verify Token": "Token verifizieren",
"Setup 2FA": "2FA einrichten",
"Enable 2FA": "2FA aktivieren",
@ -165,7 +165,7 @@
"Pink": "Pink",
"Search...": "Suchen…",
"Heartbeat Retry Interval": "Überprüfungsintervall",
"Resend Notification if Down X times consequently": "Benachrichtigung erneut senden, wenn Inaktiv X mal hintereinander",
"Resend Notification if Down X times consecutively": "Benachrichtigung erneut senden, wenn inaktiv X Mal hintereinander",
"retryCheckEverySecond": "Alle {0} Sekunden neu versuchen",
"resendEveryXTimes": "Erneut versenden alle {0} mal",
"resendDisabled": "Erneut versenden deaktiviert",
@ -206,7 +206,7 @@
"mattermost": "Mattermost",
"Primary Base URL": "Primäre Basis-URL",
"Push URL": "Push URL",
"needPushEvery": "Du solltest diese URL alle {0} Sekunden aufrufen",
"needPushEvery": "Du solltest diese URL alle {0} Sekunden aufrufen.",
"pushOptionalParams": "Optionale Parameter: {0}",
"defaultNotificationName": "Mein {notification} Alarm ({number})",
"here": "hier",
@ -215,7 +215,7 @@
"wayToGetTelegramToken": "Hier kannst du einen Token erhalten {0}.",
"Chat ID": "Chat ID",
"supportTelegramChatID": "Unterstützt Direkt Chat / Gruppe / Kanal Chat-ID's",
"wayToGetTelegramChatID": "Du kannst die Chat-ID erhalten, indem du eine Nachricht an den Bot sendest und zu dieser URL gehst, um die chat_id: zu sehen.",
"wayToGetTelegramChatID": "Du kannst deine Chat-ID erhalten, indem du eine Nachricht an den Bot sendest und zu dieser URL gehst, um die chat_id: zu sehen.",
"YOUR BOT TOKEN HERE": "HIER DEIN BOT TOKEN",
"chatIDNotFound": "Chat-ID wurde nicht gefunden: bitte sende zuerst eine Nachricht an diesen Bot",
"Post URL": "Post URL",
@ -231,7 +231,7 @@
"smtpCC": "CC",
"smtpBCC": "BCC",
"Discord Webhook URL": "Discord Webhook URL",
"wayToGetDiscordURL": "Du kannst diese erhalten, indem du zu den Servereinstellungen gehst -> Integrationen -> Neuer Webhook",
"wayToGetDiscordURL": "Du kannst diese erhalten, indem du zu den Servereinstellungen gehst -> Integrationen -> WebHooks anzeigen -> Neuer WebHook",
"Bot Display Name": "Bot-Anzeigename",
"Prefix Custom Message": "Benutzerdefinierter Nachrichten Präfix",
"Hello @everyone is...": "Hallo {'@'}everyone ist…",
@ -275,11 +275,11 @@
"Read more": "Weiterlesen",
"appriseInstalled": "Apprise ist installiert.",
"appriseNotInstalled": "Apprise ist nicht installiert. {0}",
"Access Token": "Access Token",
"Access Token": "Zugriffstoken",
"Channel access token": "Channel access token",
"Line Developers Console": "Line Developers Console",
"Line Developers Console": "Zeile Entwickler Konsole",
"lineDevConsoleTo": "Line Developers Console - {0}",
"Basic Settings": "Basic Settings",
"Basic Settings": "Grundeinstellungen",
"User ID": "User ID",
"Messaging API": "Messaging API",
"wayToGetLineChannelToken": "Rufe zuerst {0} auf, erstelle dann einen Provider und Channel (Messaging API). Als nächstes kannst du den Channel access token und die User ID aus den oben genannten Menüpunkten abrufen.",
@ -298,9 +298,9 @@
"Internal Room Id": "Interne Raum-ID",
"matrixDesc1": "Die interne Raum-ID findest du im erweiterten Bereich der Raumeinstellungen im Matrix-Client. Es sollte aussehen wie z.B. !QMdRCpUIfLwsfjxye6:home.server.",
"matrixDesc2": "Es wird dringend empfohlen einen neuen Benutzer anzulegen und nicht den Zugriffstoken deines eigenen Matrix-Benutzers zu verwenden. Anderenfalls ermöglicht es vollen Zugriff auf dein Konto und alle Räume, denen du beigetreten bist. Erstelle stattdessen einen neuen Benutzer und lade ihn nur in den Raum ein, in dem du die Benachrichtigung erhalten möchtest. Du kannst den Zugriffstoken erhalten, indem du Folgendes ausführst {0}",
"Method": "Method",
"Method": "Methode",
"Body": "Body",
"Headers": "Headers",
"Headers": "Header",
"PushUrl": "Push URL",
"HeadersInvalidFormat": "Der Header ist kein gültiges JSON: ",
"BodyInvalidFormat": "Der Body ist kein gültiges JSON: ",
@ -315,7 +315,7 @@
"Done": "Fertig",
"Info": "Info",
"Security": "Sicherheit",
"Steam API Key": "Steam API Key",
"Steam API Key": "Steam API-Schlüssel",
"Shrink Database": "Datenbank verkleinern",
"Pick a RR-Type...": "Wähle ein RR-Typ aus…",
"Pick Accepted Status Codes...": "Wähle akzeptierte Statuscodes aus…",
@ -553,14 +553,14 @@
"socket": "Socket",
"tcp": "TCP / HTTP",
"Docker Container": "Docker Container",
"Container Name / ID": "Container Name / ID",
"Docker Host": "Docker Host",
"Docker Hosts": "Docker Hosts",
"Container Name / ID": "Container-Bezeichnung / ID",
"Docker Host": "Docker-Host",
"Docker Hosts": "Docker-Hosts",
"ntfy Topic": "ntfy Thema",
"Domain": "Domain",
"Workstation": "Workstation",
"disableCloudflaredNoAuthMsg": "Du bist im nicht-authentifizieren Modus, ein Passwort wird nicht benötigt.",
"trustProxyDescription": "Vertraue 'X-Forwarded-*' headern. Wenn man die richtige client IP haben möchte und Uptime Kuma hinter einem Proxy wie Nginx or Apache läuft, wollte dies aktiviert werden.",
"trustProxyDescription": "Vertraue 'X-Forwarded-*' headern. Wenn man die richtige Client IP haben möchte und Uptime Kuma hinter einem Proxy wie Nginx oder Apache läuft, sollte dies aktiviert werden.",
"wayToGetLineNotifyToken": "Du kannst hier ein Token erhalten: {0}",
"Examples": "Beispiele",
"Home Assistant URL": "Home Assistant URL",
@ -574,7 +574,7 @@
"Event type:": "Ereignistyp:",
"Event data:": "Ereignis daten:",
"Then choose an action, for example switch the scene to where an RGB light is red.": "Dann eine Aktion wählen, zum Beispiel eine Scene wählen in der ein RGB Licht rot ist.",
"Frontend Version": "Frontend Version",
"Frontend Version": "Frontend-Version",
"Frontend Version do not match backend version!": "Die Frontend Version stimmt nicht mit der backend version überein!",
"Maintenance": "Wartung",
"statusMaintenance": "Wartung",
@ -593,7 +593,7 @@
"goAlertInfo": "GoAlert ist eine Open-Source Applikation für Rufbereitschaftsplanung, automatische Eskalation und Benachrichtigung (z.B. SMS oder Telefonanrufe). Beauftragen Sie automatisch die richtige Person, auf die richtige Art und Weise und zum richtigen Zeitpunkt. {0}",
"goAlertIntegrationKeyInfo": "Bekommt einen generischen API Schlüssel in folgenden Format \"aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee\". Normalerweise entspricht dies dem Wert des Token aus der URL.",
"goAlert": "GoAlert",
"backupOutdatedWarning": "Veraltet: Da viele Funktionen hinzugefügt wurden und diese Sicherungsfunktion nicht mehr gepflegt wird, kann sie keine vollständige Sicherung erstellen oder wiederherstellen.",
"backupOutdatedWarning": "Veraltet: Da viele Funktionen hinzugefügt wurden und diese Sicherungsfunktion nicht mehr gepflegt wird, kann keine vollständige Sicherung erstellen oder wiederherstellen werden.",
"backupRecommend": "Bitte sichere stattdessen das Volume oder den Datenordner (./data/) direkt.",
"Optional": "Optional",
"squadcast": "Squadcast",
@ -641,7 +641,60 @@
"Help": "Hilfe",
"Game": "Spiel",
"Custom": "Benutzerdefiniert",
"Enable DNS Cache": "DNS Cache aktivieren",
"Enable DNS Cache": "DNS-Cache aktivieren",
"Enable": "Aktivieren",
"Disable": "Deaktivieren"
"Disable": "Deaktivieren",
"Custom Monitor Type": "Benutzerdefinierter Monitortyp",
"webhookAdditionalHeadersDesc": "Legt zusätzliche Header fest, die mit der Webhook gesendet wurden.",
"dnsCacheDescription": "In einigen IPv6-Umgebungen funktioniert es möglicherweise nicht. Deaktivieren Sie es, wenn Sie auf Probleme stoßen.",
"loadingError": "Die Daten konnten nicht abgerufen werden, bitte später noch einmal versuchen.",
"confirmUninstallPlugin": "Möchten Sie dieses Plugin wirklich deinstallieren?",
"grpcMethodDescription": "Der Name der Methode wird in das \"cammelCase \"-Format konvertiert (z.B. sayHello, check, etc.)",
"Passive Monitor Type": "Passiver Monitortyp",
"Specific Monitor Type": "Spezifischer Monitortyp",
"webhookAdditionalHeadersTitle": "Zusätzliche Header",
"Packet Size": "Paketgröße",
"IconUrl": "Symbol-URL",
"wayToGetZohoCliqURL": "Erfahren Sie, wie Sie eine Webhook-URL {0} erstellen.",
"dataRetentionTimeError": "Aufbewahrungszeit muss 0 oder größer sein",
"infiniteRetention": "Für unendliche Aufbewahrung auf 0 setzen.",
"confirmDeleteTagMsg": "Möchten Sie dieses Tag wirklich löschen? Mit diesem Tag verknüpfte Monitore werden nicht gelöscht.",
"enableGRPCTls": "Erlaube das Senden von gRPC-Anfragen mit TLS-Verbindung",
"ZohoCliq": "ZohoCliq",
"Monitor": "Überwachung | Monitore",
"plugin": "Plugin | Plugins",
"install": "Installieren",
"installing": "Installiere",
"uninstall": "Deinstallieren",
"uninstalling": "Deinstallation",
"markdownSupported": "Markdown-Syntax unterstützt",
"wayToGetKookBotToken": "Anwendung erstellen und den Bot-Token {0} abrufen",
"wayToGetKookGuildID": "Schalten Sie den \"Entwicklermodus\" in den Kook-Einstellungen ein und klicken Sie mit der rechten Maustaste auf die Gilde, um ihre ID zu erhalten.",
"Guild ID": "Gilden-ID",
"Free Mobile User Identifier": "Kostenlose mobile Benutzerkennung",
"Free Mobile API Key": "Kostenloser Mobile API-Schlüssel",
"Enable TLS": "Aktiviere TLS",
"Proto Service Name": "Proto Service Name",
"Proto Method": "Proto Methode",
"Proto Content": "Proto Inhalt",
"Economy": "Economy-Modus",
"Lowcost": "Lowcost-Modus",
"high": "High-Modus",
"promosmsAllowLongSMS": "Erlaube lange SMS",
"General Monitor Type": "Allgemeiner Monitortyp",
"smseagle": "SMSEagle",
"smseagleTo": "Telefonnummer(n)",
"smseagleGroup": "Telefonbuch Gruppenname(n)",
"smseagleContact": "Telefonbuch Kontaktname(n)",
"smseagleRecipientType": "Empfängertyp",
"smseagleRecipient": "Empfänger (mehrere müssen mit Komma getrennt werden)",
"smseagleToken": "API-Zugriffstoken",
"smseagleUrl": "Deine SMSEagle-Geräte-URL",
"Kook": "Kook",
"smseagleEncoding": "Als Unicode senden",
"smseaglePriority": "Nachrichtenpriorität (0-9, Standard = 0)",
"Google Analytics ID": "Google Analytics ID",
"Edit Tag": "bearbeite Tag",
"Server Address": "Server Adresse",
"Learn More": "Erfahre mehr"
}

@ -25,8 +25,8 @@
"confirmClearStatisticsMsg": "Είστε βέβαιοι ότι θέλετε να διαγράψετε ΟΛΑ τα στατιστικά στοιχεία;?",
"importHandleDescription": "Επιλέξτε «Παράλειψη υπάρχοντος» εάν θέλετε να παραλείψετε κάθε παρακολούθηση ή ειδοποίηση με το ίδιο όνομα. Το 'Overwrite' θα διαγράψει κάθε υπάρχουσα παρακολούθηση και ειδοποίηση.",
"confirmImportMsg": "Είστε βέβαιοι ότι θέλετε να εισαγάγετε το αντίγραφο ασφαλείας; Επαληθεύστε ότι έχετε επιλέξει τη σωστή επιλογή.",
"twoFAVerifyLabel": "Εισαγάγετε το 2FA κωδικό για να επαληθεύσετε: ",
"tokenValidSettingsMsg": "Ο κωδικός 2FA είναι έγκυρο! Τώρα μπορείτε να αποθηκεύσετε τις ρυθμίσεις 2FA",
"twoFAVerifyLabel": "Εισαγάγετε το 2FA κωδικό για να επαληθεύσετε:",
"tokenValidSettingsMsg": "Ο κωδικός 2FA είναι έγκυρος! Τώρα μπορείτε να αποθηκεύσετε τις ρυθμίσεις 2FA.",
"confirmEnableTwoFAMsg": "Είστε βέβαιοι ότι θέλετε να ενεργοποιήσετε το 2FA;",
"confirmDisableTwoFAMsg": "Είστε βέβαιοι ότι θέλετε να απενεργοποιήσετε το 2FA;",
"Settings": "Ρυθμίσεις",
@ -56,9 +56,9 @@
"Resume": "Συνέχιση",
"Edit": "Επεξεργασία",
"Delete": "Διαγράφη",
"Current": "Current",
"Current": "Τρέχον",
"Uptime": "Χρόνος λειτουργίας",
"Cert Exp.": "Cert Exp.",
"Cert Exp.": "Λήξη Πιστοπ.",
"day": "ημέρα | ημέρες",
"-day": "-ημέρα",
"hour": "ώρα",
@ -74,7 +74,7 @@
"Heartbeat Interval": "Διάστημα καρδιακών παλμών",
"Retries": "Επαναλήψεις",
"Heartbeat Retry Interval": "Διάστημα επανάληψης παλμών καρδιάς",
"Resend Notification if Down X times consequently": "Αποστολή νέας ειδοποίησης εάν κατω X φορές κατά συνέχεια",
"Resend Notification if Down X times consecutively": "Αποστολή νέας ειδοποίησης εάν κατω X φορές κατά συνέχεια",
"Advanced": "Προχωρημένα",
"Upside Down Mode": "Ανάποδη λειτουργία",
"Max. Redirects": "Μέγιστη. Ανακατευθύνσεις",
@ -162,11 +162,11 @@
"Token": "Token",
"Show URI": "Εμφάνιση URI",
"Tags": "Ετικέτες",
"Add New below or Select...": "Προσθήκη νέου παρακάτω ή Επιλέξτε...",
"Add New below or Select...": "Προσθήκη νέου παρακάτω ή Επιλέξτε",
"Tag with this name already exist.": "Υπάρχει ήδη η ετικέτα με αυτό το όνομα.",
"Tag with this value already exist.": "Υπάρχει ήδη ετικέτα με αυτό το value.",
"color": "χρώμα",
"value (optional)": "value (optional)",
"value (optional)": "τιμή (προαιρετικό)",
"Gray": "Γκρί",
"Red": "Κόκκινο",
"Orange": "Πορτοκάλι",
@ -175,7 +175,7 @@
"Indigo": "Indigo",
"Purple": "Μωβ",
"Pink": "Ροζ",
"Search...": "Αναζήτηση...",
"Search...": "Αναζήτηση",
"Avg. Ping": "Μέσo.Ping",
"Avg. Response": "Μέσo. Aπάντηση",
"Entry Page": "Σελίδα εισαγωγής",
@ -218,10 +218,10 @@
"smtpBCC": "BCC",
"discord": "Discord",
"Discord Webhook URL": "Discord Webhook URL",
"wayToGetDiscordURL": "Μπορείτε να το αποκτήσετε μεταβαίνοντας στις Ρυθμίσεις διακομιστή -> Ενσωματώσεις -> Δημιουργία Webhook",
"wayToGetDiscordURL": "Μπορείτε να το αποκτήσετε μεταβαίνοντας στις Ρυθμίσεις διακομιστή -> Ενσωματώσεις -> Προβολή των Webhooks -> Νέο Webhook",
"Bot Display Name": "Εμφανιζόμενο όνομα bot",
"Prefix Custom Message": "Προσαρμοσμένο μήνυμα",
"Hello @everyone is...": "Γεια {'@'}everyone ειναι...",
"Hello @everyone is...": "Γεια {'@'}everyone είναι…",
"teams": "Microsoft Teams",
"Webhook URL": "Webhook URL",
"wayToGetTeamsURL": "Μπορείτε να μάθετε πώς να δημιουργείτε μια διεύθυνση URL webhook {0}.",
@ -271,7 +271,7 @@
"apiCredentials": "API credentials",
"octopushLegacyHint": "Χρησιμοποιείτε την παλαιού τύπου έκδοση του Octopush (2011-2020) ή τη νέα έκδοση;",
"Check octopush prices": "Ελέγξτε τις τιμές OctoPush {0}.",
"octopushPhoneNumber": "Αριθμός τηλεφώνου (διεθνής μορφή, π.χ.: +30694345678)",
"octopushPhoneNumber": "Αριθμός τηλεφώνου (διεθνής μορφή, π.χ.: +30694345678) ",
"octopushSMSSender": "Όνομα αποστολέα SMS: 3-11 αλφαριθμητικοί χαρακτήρες και διάστημα (a-zA-Z0-9)",
"LunaSea Device ID": "LunaSea Device ID",
"Apprise URL": "Apprise URL",
@ -306,10 +306,10 @@
"matrixDesc2": "Συνιστάται ανεπιφύλακτα να δημιουργήσετε έναν νέο χρήστη και να μην χρησιμοποιήσετε το διακριτικό πρόσβασης του χρήστη Matrix, καθώς θα επιτρέψει την πλήρη πρόσβαση στον λογαριασμό σας και σε όλα τα δωμάτια στα οποία συμμετέχετε. Αντίθετα, δημιουργήστε έναν νέο χρήστη και προσκαλέστε τον μόνο στο δωμάτιο στο οποίο θέλετε να λαμβάνετε την ειδοποίηση. Μπορείτε να λάβετε το access token εκτελώντας {0}",
"Method": "Μέθοδος",
"Body": "Σώμα",
"Headers": "Headers",
"Headers": "Κεφαλίδες",
"PushUrl": "Push URL",
"HeadersInvalidFormat": "The request headers are not valid JSON: ",
"BodyInvalidFormat": "The request body is not valid JSON: ",
"HeadersInvalidFormat": "Οι κεφαλίδες του αιτήματος δεν αποτελούν έγκυρο JSON: ",
"BodyInvalidFormat": "Το περιεχόμενο/σώμα του αιτήματος δεν αποτελεί έγκυρο JSON: ",
"Monitor History": "Ιστορικο Παρακολούθησης",
"clearDataOlderThan": "Διατηρήστε τα δεδομένα ιστορικού παρακολούθησης για {0} ημέρες.",
"PasswordsDoNotMatch": "Οι κωδικοί πρόσβασης δεν ταιριάζουν.",
@ -327,8 +327,8 @@
"Security": "Ασφάλεια",
"Steam API Key": "Steam API Key",
"Shrink Database": "Συρρίκνωση βάσης δεδομένων",
"Pick a RR-Type...": "Επιλέξτε έναν τύπο RR...",
"Pick Accepted Status Codes...": "Επιλέξτε Αποδεκτούς κωδικούς κατάστασης...",
"Pick a RR-Type...": "Επιλέξτε έναν τύπο RR",
"Pick Accepted Status Codes...": "Επιλέξτε Αποδεκτούς κωδικούς κατάστασης",
"Default": "Προκαθορισμένο",
"HTTP Options": "Επιλογές HTTP",
"Create Incident": "Δημιουργία περιστατικού",
@ -340,9 +340,9 @@
"danger": "κίνδυνος",
"error": "σφάλμα",
"critical": "κριτικό",
"primary": "primary",
"light": "light",
"dark": "dark",
"primary": "κύριο",
"light": "φωτεινό",
"dark": "σκοτεινό",
"Post": "Δημοσίευση",
"Please input title and content": "Παρακαλούμε εισαγάγετε τίτλο και περιεχόμενο",
"Created": "Δημιουργήθηκε",
@ -403,7 +403,7 @@
"proxyDescription": "Πρέπει να εκχωρηθούν proxies σε μια οθπαρακολουθή για να λειτουργήσουν..",
"enableProxyDescription": "Το proxy δεν θα επηρεάσει τα αιτήματα της παρακολουθήσεις μέχρι να ενεργοποιηθεί. Μπορείτε να ελέγξετε την προσωρινή απενεργοποίηση του proxy από όλες τις παρακολουθήσεις βάσει κατάστασης ενεργοποίησης.",
"setAsDefaultProxyDescription": "Αυτός το proxy θα είναι ενεργοποιημένο από προεπιλογή για νέες παρακολουθήσεις. Μπορείτε ακόμα να απενεργοποιήσετε το proxy ξεχωριστά για κάθε οθόνη.",
"Certificate Chain": "Certificate Chain",
"Certificate Chain": "Αλυσίδα Πιστοποιητικών",
"Valid": "Εγκυρο",
"Invalid": "Μη έγκυρο",
"AccessKeyId": "AccessKey ID",
@ -460,7 +460,7 @@
"Message:": "Μήνυμα:",
"Don't know how to get the token? Please read the guide:": "Δεν ξέρετε πώς να αποκτήσετε το token; Διαβάστε τον οδηγό:",
"The current connection may be lost if you are currently connecting via Cloudflare Tunnel. Are you sure want to stop it? Type your current password to confirm it.": "Η τρέχουσα σύνδεση μπορεί να χαθεί εάν αυτή τη στιγμή συνδέεστε μέσω του Cloudflare Tunnel. Θέλετε σίγουρα να το σταματήσετε; Πληκτρολογήστε τον τρέχοντα κωδικό πρόσβασής σας για να τον επιβεβαιώσετε.",
"HTTP Headers": "HTTP Headers",
"HTTP Headers": "Κεφαλίδες HTTP",
"Trust Proxy": "Εμπιστοσύνη του Proxy",
"Other Software": "Other Software",
"For example: nginx, Apache and Traefik.": "Για παράδειγμα: nginx, Apache και Traefik.",
@ -562,11 +562,11 @@
"Domain": "Domain",
"Workstation": "Workstation",
"disableCloudflaredNoAuthMsg": "Βρίσκεστε σε λειτουργία No Auth, δεν απαιτείται κωδικός πρόσβασης.",
"trustProxyDescription": "Εμπιστευτείτε τις κεφαλίδες 'X-Forwarded-*'. Εάν θέλετε να λάβετε τη σωστή IP πελάτη και το Uptime Kuma σας βρίσκεται πίσω το Nginx ή το Apache, θα πρέπει να το ενεργοποιήσετε.",
"trustProxyDescription": "Εμπιστευτείτε τις κεφαλίδες 'X-Forwarded-*'. Εάν θέλετε να λάβετε τη σωστή IP πελάτη και το Uptime Kuma σας βρίσκεται πίσω κάποιος proxy όπως το Nginx ή το Apache, θα πρέπει να το ενεργοποιήσετε.",
"wayToGetLineNotifyToken": "Μπορείτε να λάβετε ένα access token από το {0}",
"Examples": "Παραδείγματα",
"Home Assistant URL": "Home Assistant URL",
"Long-Lived Access Token": "Long-Lived Access Token",
"Long-Lived Access Token": "Μακράς-Διάρκειας Κλειδί Τόκεν",
"Long-Lived Access Token can be created by clicking on your profile name (bottom left) and scrolling to the bottom then click Create Token. ": "Long-Lived Access Token μπορεί να δημιουργηθεί κάνοντας κλικ στο όνομα του προφίλ σας (κάτω αριστερά) και κάνοντας κύλιση προς τα κάτω και, στη συνέχεια, κάντε κλικ στο Create Token. ",
"Notification Service": "Υπηρεσία ειδοποιήσεων",
"default: notify all devices": "προεπιλογή: ειδοποίηση όλων των συσκευών",
@ -582,6 +582,118 @@
"goAlertInfo": "Το GoAlert είναι μια εφαρμογή ανοιχτού κώδικα για προγραμματισμό κλήσεων, αυτοματοποιημένες κλιμακώσεις και ειδοποιήσεις (όπως SMS ή φωνητικές κλήσεις). Αλληλεπιδράστε αυτόματα με το σωστό άτομο, με τον σωστό τρόπο και τη σωστή στιγμή! {0}",
"goAlertIntegrationKeyInfo": "Λάβετε το generic API integration key για την υπηρεσία σε αυτήν τη μορφή \"aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee\" συνήθως την τιμή της παραμέτρου διακριτικού της αντιγραμμένης διεύθυνσης URL.",
"goAlert": "GoAlert",
"backupOutdatedWarning": "Καταργήθηκε: Επειδή προστέθηκαν πολλές δυνατότητες και αυτή η δυνατότητα δημιουργίας αντιγράφων ασφαλείας δεν διατηρείται πολη, δεν μπορεί να δημιουργήσει ή να επαναφέρει ένα πλήρες αντίγραφο ασφαλείας.",
"backupRecommend": "Παρακαλούμε δημιουργήστε αντίγραφα ασφαλείας του volume ή του φακέλου δεδομένων (./data/) απευθείας."
"backupOutdatedWarning": "Καταργήθηκε: Επειδή προστέθηκαν πολλές δυνατότητες και αυτή η δυνατότητα δημιουργίας αντιγράφων ασφαλείας δεν διατηρείται, δεν μπορεί να δημιουργήσει ή να επαναφέρει ένα πλήρες αντίγραφο ασφαλείας.",
"backupRecommend": "Παρακαλούμε δημιουργήστε αντίγραφα ασφαλείας του volume ή του φακέλου δεδομένων (./data/) απευθείας.",
"Maintenance": "Συντήρηση",
"General Monitor Type": "Επόπτης Γενικού Τύπου",
"maintenanceStatus-under-maintenance": "Υπό Συντήρηση",
"dnsCacheDescription": "Μπορεί να μη λειτουργεί σε κάποια IPv6 περιβάλλοντα, απενεργοποιήστε αν συναντήσετε προβλήματα.",
"uninstalling": "Γίνεται απεγκατάσταση",
"confirmUninstallPlugin": "Θέλετε σίγουρα να απεγκαταστήσετε αυτό το πρόσθετο;",
"smseagle": "SMSEagle",
"smseagleRecipientType": "Τύπος παραλήπτη",
"smseagleUrl": "Το URL της SMSEagle συσκευής σας",
"Start of maintenance": "Έναρξη συντήρησης",
"All Status Pages": "Όλες οι Σελίδες Κατάστασης",
"Select status pages...": "Επιλέξτε σελίδες κατάστασης…",
"Optional": "Προαιρετικό",
"weekdayShortMon": "Δευ",
"weekdayShortTue": "Τρι",
"weekdayShortWed": "Τετ",
"weekdayShortThu": "Πεμ",
"weekdayShortFri": "Παρ",
"weekdayShortSat": "Σαβ",
"Help": "Βοήθεια",
"Game": "Παιχνίδι",
"Specific Monitor Type": "Επόπτης Συγκεκριμένου Τύπου",
"Passive Monitor Type": "Επόπτης Παθητικού Τύπου",
"Monitor": "Επόπτης | Επόπτες",
"Schedule maintenance": "Προγραμματισμός συντήρησης",
"Affected Monitors": "Επηρεαζόμενοι Επόπτες",
"Pick Affected Monitors...": "Διαλέξτε Επηρεαζόμενους Επόπτες…",
"webhookAdditionalHeadersTitle": "Επιπρόσθετες Κεφαλίδες",
"webhookAdditionalHeadersDesc": "Ορίζει επιπρόσθετες κεφαλίδες που θα σταλθούν με το webhook.",
"weekdayShortSun": "Κυρ",
"dayOfWeek": "Ημέρα της Εβδομάδας",
"dayOfMonth": "Ημέρα του Μήνα",
"lastDay1": "Τελευταία Μέρα του Μήνα",
"lastDay2": "2η Τελευταία Μέρα του Μήνα",
"lastDay3": "3η Τελευταία Μέρα του Μήνα",
"lastDay4": "4η Τελευταία Μέρα του Μήνα",
"lastDay": "Τελευταία Μέρα",
"No Maintenance": "Όχι Συντήρηση",
"pauseMaintenanceMsg": "Είστε σίγουροι για την παύση;",
"maintenanceStatus-inactive": "Ανενεργό",
"maintenanceStatus-scheduled": "Προγραμματισμένο",
"maintenanceStatus-ended": "Ολοκληρωμένο",
"maintenanceStatus-unknown": "Άγνωστο",
"Display Timezone": "Προβολή Ζώνης Ώρας",
"Server Timezone": "Ζώνη Ώρας του Server",
"statusPageMaintenanceEndDate": "Λήξη",
"Custom": "Προσαρμοσμένο",
"Economy": "Οικονομία",
"loadingError": "Αδύνατη συλλογή δεδομένων, προσπαθήστε ξανά αργότερα.",
"SendKey": "SendKey",
"SMSManager API Docs": "API βιβλιογραφία του SMSManager ",
"Kook": "Kook",
"statusMaintenance": "Συντήρηση",
"markdownSupported": "Υποστήριξη markdown συντακτικού",
"Packet Size": "Μέγεθος Πακέτου",
"or": "ή",
"recurringInterval": "Χρονικό Διάστημα",
"Recurring": "Επαναλαμβανόμενο",
"strategyManual": "Ενεργό/Ανενεργό Χειροκίνητα",
"warningTimezone": "Χρησιμοποιεί την ζώνη ώρας του server",
"squadcast": "Squadcast",
"IconUrl": "URL εικονιδίου",
"Enable DNS Cache": "Ενεργοποίηση DNS Cache",
"Enable": "Ενεργοποίηση",
"Disable": "Απενεργοποίηση",
"Single Maintenance Window": "Μονό Παράθυρο Συντήρησης",
"Maintenance Time Window of a Day": "Ημερίσιο πρόγραμμα Συντήρησης",
"Effective Date Range": "Ημερομηνιακό Διάστημα Εφαρμογής",
"Schedule Maintenance": "Προγραμματισμός Συντήρησης",
"Date and Time": "Ημερομηνία και Ώρα",
"DateTime Range": "Ημερομηνιακό Πλαίσιο",
"plugin": "Πρόσθετο | Πρόσθετα",
"install": "Εγκατάσταση",
"installing": "Γίνεται εγκατάσταση",
"uninstall": "Απεγκατάσταση",
"dataRetentionTimeError": "Η περίοδος διατήρησης πρέπει να είναι 0 ή μεγαλύτερο",
"infiniteRetention": "Ορίστε 0 για μόνιμη διατήρηση.",
"confirmDeleteTagMsg": "Θέλετε σίγουρα να διαγράψετε αυτήν την ετικέτα; Οι επόπτες που σχετίζονται με αυτήν την ετικέτα δεν θα διαγραφούν.",
"enableGRPCTls": "Επιτρέψτε την αποστολή gRPC αιτημάτων μέσω TLS συνδέσεων",
"grpcMethodDescription": "Το όνομα της μεθόδου μετατρέπεται σε cammelCase μορφή όπως π.χ. sayHello, check, κλπ.",
"deleteMaintenanceMsg": "Θέλετε σίγουρα να διαγράψετε αυτή την συντήρηση;",
"recurringIntervalMessage": "Εκτέλεση μια φορά την ημέρα | Εκτέλεση μία φορά ανά {0} ημέρες",
"affectedMonitorsDescription": "Επιλέξτε τους επόπτες που επηρεάζονται από την τωρινή συντήρηση",
"affectedStatusPages": "Προβολή αυτού του μηνύματος συντήρησης σε επιλεγμένες σελίδες κατάστασης",
"atLeastOneMonitor": "Επιλέξτε τουλάχιστον έναν επηρεασμένο επόπτη",
"wayToGetKookBotToken": "Δημιουργήστε εφαρμογή και πάρτε το bot token στο {0}",
"wayToGetKookGuildID": "Ενεργοποιήστε την 'Λειτουργία Προγραμματιστή' στις ρυθμίσεις Kook, και κάντε δεξί κλικ στο guild για να πάρετε το ID του",
"Guild ID": "Guild ID",
"Strategy": "Στρατηγική",
"Enable TLS": "Ενεργοποίηση TLS",
"Proto Service Name": "Όνομα Υπηρεσίας Proto",
"Proto Method": "Μέθοδος Proto",
"Proto Content": "Περιεχόμενο Proto",
"Lowcost": "Χαμηλό κόστος",
"high": "υψηλό",
"Gateway Type": "Τύπος Πύλης",
"SMSManager": "SMSManager",
"You can divide numbers with": "Μπορείτε να διαιρέσετε αριθμούς με",
"promosmsAllowLongSMS": "Επέτρεψε SMS μεγάλου μεγέθους",
"smseagleTo": "Αριθμός(οί) τηλεφώνου",
"smseagleGroup": "Όνομα/Ονόματα γκρουπ καταλόγων",
"smseagleContact": "Όνομα/Ονόματα επαφών καταλόγου",
"smseagleRecipient": "Παραλήπτης(ες) (πολλαπλοί πρέπει να διαχωρίζονται με κόμμα)",
"smseagleToken": "API Κλειδί τόκεν",
"smseagleEncoding": "Αποστολή ως Unicode",
"Custom Monitor Type": "Προσαρμοσμένος Τύπος Επόπτη",
"Edit Tag": "Επεξεργασία Ετικέτας",
"Server Address": "Διεύθυνση Διακομιστή",
"Learn More": "Μάθετε περισσότερα",
"Free Mobile User Identifier": "Free Mobile User Identifier",
"Free Mobile API Key": "Free Mobile API Key",
"smseaglePriority": "Προτεραιότητα μηνύματος (0-9, προεπιλογή = 0)"
}

@ -55,7 +55,7 @@
"Heartbeat Interval": "Heartbeat Interval",
"Retries": "Retries",
"Heartbeat Retry Interval": "Heartbeat Retry Interval",
"Resend Notification if Down X times consequently": "Resend Notification if Down X times consequently",
"Resend Notification if Down X times consecutively": "Resend Notification if Down X times consecutively",
"Advanced": "Advanced",
"checkEverySecond": "Check every {0} seconds",
"retryCheckEverySecond": "Retry every {0} seconds",
@ -186,7 +186,6 @@
"defaultNotificationName": "My {notification} Alert ({number})",
"here": "here",
"Required": "Required",
"webhook": "Webhook",
"Post URL": "Post URL",
"Content Type": "Content Type",
"webhookJsonDesc": "{0} is good for any modern HTTP servers such as Express.js",
@ -359,11 +358,15 @@
"Domain": "Domain",
"Workstation": "Workstation",
"Packet Size": "Packet Size",
"telegram": "Telegram",
"ZohoCliq": "ZohoCliq",
"Bot Token": "Bot Token",
"wayToGetTelegramToken": "You can get a token from {0}.",
"Chat ID": "Chat ID",
"telegramMessageThreadID": "(Optional) Message Thread ID",
"telegramMessageThreadIDDescription": "Optional Unique identifier for the target message thread (topic) of the forum; for forum supergroups only",
"telegramSendSilently": "Send Silently",
"telegramSendSilentlyDescription": "Sends the message silently. Users will receive a notification with no sound.",
"telegramProtectContent": "Protect Forwarding/Saving",
"telegramProtectContentDescription": "If enabled, the bot messages in Telegram will be protected from forwarding and saving.",
"supportTelegramChatID": "Support Direct Chat / Group / Channel's Chat ID",
"wayToGetTelegramChatID": "You can get your chat ID by sending a message to the bot and going to this URL to view the chat_id:",
"YOUR BOT TOKEN HERE": "YOUR BOT TOKEN HERE",
@ -388,7 +391,6 @@
"backupOutdatedWarning": "Deprecated: Since a lot of features were added and this backup feature is a bit unmaintained, it cannot generate or restore a complete backup.",
"backupRecommend": "Please backup the volume or the data folder (./data/) directly instead.",
"Optional": "Optional",
"squadcast": "Squadcast",
"or": "or",
"recurringInterval": "Interval",
"Recurring": "Recurring",
@ -436,6 +438,11 @@
"uninstall": "Uninstall",
"uninstalling": "Uninstalling",
"confirmUninstallPlugin": "Are you sure want to uninstall this plugin?",
"notificationRegional": "Regional",
"Clone Monitor": "Clone Monitor",
"Clone": "Clone",
"cloneOf": "Clone of {0}",
"Description": "Description",
"smtp": "Email (SMTP)",
"secureOptionNone": "None / STARTTLS (25, 587)",
"secureOptionTLS": "TLS (465)",
@ -446,7 +453,7 @@
"smtpCC": "CC",
"smtpBCC": "BCC",
"Discord Webhook URL": "Discord Webhook URL",
"wayToGetDiscordURL": "You can get this by going to Server Settings -> Integrations -> Create Webhook",
"wayToGetDiscordURL": "You can get this by going to Server Settings -> Integrations -> View Webhooks -> New Webhook",
"Bot Display Name": "Bot Display Name",
"Prefix Custom Message": "Prefix Custom Message",
"Hello @everyone is...": "Hello {'@'}everyone is…",
@ -530,28 +537,11 @@
"pushoversounds none": "None (silent)",
"pushyAPIKey": "Secret API Key",
"pushyToken": "Device token",
"discord": "Discord",
"teams": "Microsoft Teams",
"signal": "Signal",
"gotify": "Gotify",
"slack": "Slack",
"rocket.chat": "Rocket.Chat",
"pushover": "Pushover",
"pushy": "Pushy",
"PushByTechulus": "Push by Techulus",
"octopush": "Octopush",
"promosms": "PromoSMS",
"clicksendsms": "ClickSend SMS",
"lunasea": "LunaSea",
"apprise": "Apprise (Support 50+ Notification services)",
"GoogleChat": "Google Chat (Google Workspace only)",
"pushbullet": "Pushbullet",
"Kook": "Kook",
"wayToGetKookBotToken": "Create application and get your bot token at {0}",
"wayToGetKookGuildID": "Switch on 'Developer Mode' in Kook setting, and right click the guild to get its ID",
"Guild ID": "Guild ID",
"line": "Line Messenger",
"mattermost": "Mattermost",
"User Key": "User Key",
"Device": "Device",
"Message Title": "Message Title",
@ -586,12 +576,10 @@
"SendKey": "SendKey",
"SMSManager API Docs": "SMSManager API Docs ",
"Gateway Type": "Gateway Type",
"SMSManager": "SMSManager",
"You can divide numbers with": "You can divide numbers with",
"Base URL": "Base URL",
"goAlertInfo": "GoAlert is a An open source application for on-call scheduling, automated escalations and notifications (like SMS or voice calls). Automatically engage the right person, the right way, and at the right time! {0}",
"goAlertIntegrationKeyInfo": "Get generic API integration key for the service in this format \"aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee\" usually the value of token parameter of copied URL.",
"goAlert": "GoAlert",
"AccessKeyId": "AccessKey ID",
"SecretAccessKey": "AccessKey Secret",
"PhoneNumbers": "PhoneNumbers",
@ -606,7 +594,6 @@
"For safety, must use secret key": "For safety, must use secret key",
"Device Token": "Device Token",
"Platform": "Platform",
"iOS": "iOS",
"Android": "Android",
"Huawei": "Huawei",
"High": "High",
@ -617,7 +604,6 @@
"Proxy Protocol": "Proxy Protocol",
"Proxy Server": "Proxy Server",
"Proxy server has authentication": "Proxy server has authentication",
"matrix": "Matrix",
"promosmsTypeEco": "SMS ECO - cheap but slow and often overloaded. Limited only to Polish recipients.",
"promosmsTypeFlash": "SMS FLASH - Message will automatically show on recipient device. Limited only to Polish recipients.",
"promosmsTypeFull": "SMS FULL - Premium tier of SMS, You can use your Sender Name (You need to register name first). Reliable for alerts.",
@ -653,19 +639,15 @@
"do nothing": "do nothing",
"auto acknowledged": "auto acknowledged",
"auto resolve": "auto resolve",
"gorush": "Gorush",
"alerta": "Alerta",
"alertaApiEndpoint": "API Endpoint",
"alertaEnvironment": "Environment",
"alertaApiKey": "API Key",
"alertaAlertState": "Alert State",
"alertaRecoverState": "Recover State",
"serwersms": "SerwerSMS.pl",
"serwersmsAPIUser": "API Username (incl. webapi_ prefix)",
"serwersmsAPIPassword": "API Password",
"serwersmsPhoneNumber": "Phone number",
"serwersmsSenderName": "SMS Sender Name (registered via customer portal)",
"smseagle": "SMSEagle",
"smseagleTo": "Phone number(s)",
"smseagleGroup": "Phonebook group name(s)",
"smseagleContact": "Phonebook contact name(s)",
@ -675,14 +657,12 @@
"smseagleUrl": "Your SMSEagle device URL",
"smseagleEncoding": "Send as Unicode",
"smseaglePriority": "Message priority (0-9, default = 0)",
"stackfield": "Stackfield",
"Recipient Number": "Recipient Number",
"From Name/Number": "From Name/Number",
"Leave blank to use a shared sender number.": "Leave blank to use a shared sender number.",
"Octopush API Version": "Octopush API Version",
"Legacy Octopush-DM": "Legacy Octopush-DM",
"ntfy Topic": "ntfy Topic",
"HomeAssistant": "Home Assistant",
"onebotHttpAddress": "OneBot HTTP Address",
"onebotMessageType": "OneBot Message Type",
"onebotGroupMessage": "Group",
@ -696,6 +676,24 @@
"Edit Tag": "Edit Tag",
"Server Address": "Server Address",
"Learn More": "Learn More",
"Body Encoding": "Body Encoding",
"API Keys": "API Keys",
"Expiry": "Expiry",
"Expiry date": "Expiry date",
"Don't expire": "Don't expire",
"Continue": "Continue",
"Add Another": "Add Another",
"Key Added": "Key Added",
"apiKeyAddedMsg": "Your API key has been added. Please make a note of it as it will not be shown again.",
"Add API Key": "Add API Key",
"No API Keys": "No API Keys",
"apiKey-active": "Active",
"apiKey-expired": "Expired",
"apiKey-inactive": "Inactive",
"Expires": "Expires",
"disableAPIKeyMsg": "Are you sure you want to disable this API key?",
"deleteAPIKeyMsg": "Are you sure you want to delete this API key?",
"Generate": "Generate",
"pagertreeIntegrationUrl": "Integration URL",
"pagertreeUrgency": "Urgency",
"pagertreeSilent": "Silent",

@ -304,7 +304,7 @@
"General Monitor Type": "Monitor Tipo General",
"Specific Monitor Type": "Monitor Tipo Específico",
"Monitor": "Monitores",
"Resend Notification if Down X times consequently": "Reenviar Notificación si Caído X veces consecutivas",
"Resend Notification if Down X times consecutively": "Reenviar Notificación si Caído X veces consecutivamente",
"resendEveryXTimes": "Reenviar cada {0} veces",
"resendDisabled": "Reenvío deshabilitado",
"needPushEvery": "Debe llamar a esta URL cada {0} segundos.",
@ -392,7 +392,7 @@
"webhookAdditionalHeadersDesc": "Establece encabezados adicionales enviados con el webhook.",
"appriseInstalled": "Apprise está instalado.",
"successMessage": "Mensaje de éxito",
"Pick Accepted Status Codes...": "Elija códigos de estado aceptados…",
"Pick Accepted Status Codes...": "Seleccione Códigos de Estado Aceptados…",
"Post": "Post",
"shrinkDatabaseDescription": "Activar ASPIRADORA para SQLite. Si tu base de datos fue creada después 1.10.0, AUTO_ASPIRADORA ya está habilitada y esta acción no es necesaria.",
"deleteStatusPageMsg": "¿Estas seguro que quieres eliminar esta página de estado?",
@ -534,7 +534,7 @@
"smtpCC": "CC",
"smtpBCC": "CCO",
"Discord Webhook URL": "URL Webhook de Discord",
"wayToGetDiscordURL": "Puede obtener esto yendo a Configuración del servidor -> Integraciones -> Crear webhook",
"wayToGetDiscordURL": "Puede obtener esto yendo a Configuración del servidor -> Integraciones -> Ver Webhooks -> Crear Webhook",
"Bot Display Name": "Nombre para mostrar del Bot",
"Hello @everyone is...": "Hola {'@'}todos están…",
"wayToGetTeamsURL": "Puedes aprender cómo crear una URL webhook {0}.",
@ -591,7 +591,7 @@
"Kook": "Kook",
"wayToGetKookBotToken": "Crea aplicación y obtén tu token de bot en {0}",
"wayToGetKookGuildID": "Activa 'Modo Desarrollador' en los ajustes de Kook, y haz click derecho en la unión para obtener su ID",
"Guild ID": "",
"Guild ID": "ID de Gremio",
"User Key": "Key de Usuario",
"octopushTypePremium": "Premium (Rápido - recomendado para alertas)",
"octopushTypeLowCost": "Bajo Coste (Lento - algunas veces bloqueado por operador)",
@ -655,5 +655,38 @@
"gorush": "Gorush",
"squadcast": "Squadcast",
"Maintenance Time Window of a Day": "Ventana de tiempo de mantenimiento de un día",
"Effective Date Range": "Rango de Fecha Efectivo"
"Effective Date Range": "Rango de Fecha Efectivo",
"Free Mobile User Identifier": "Identificador de Usuario de Free Mobile",
"Gateway Type": "Tipo de Puerta de Enlace",
"SMSManager": "SMSManager",
"goAlertInfo": "GoAlert es una aplicación de código abierto para la programación de guardias, escaladas automatizadas y notificaciones (como SMS o llamadas de voz). ¡Involucre automáticamente a la persona adecuada, de la manera correcta y en el momento adecuado! {0}",
"Free Mobile API Key": "Clave API de Free Mobile",
"high": "alto",
"SMSManager API Docs": "Documentación API de SMSManager ",
"smseagleContact": "Nombre(s) de contacto de Guía Telefónica",
"smseagleToken": "Token de Acceso a la API",
"smseagleUrl": "URL del dispositivo SMSEagle",
"Legacy Octopush-DM": "Octopush-DM heredado",
"HomeAssistant": "Home Assistant",
"goAlertIntegrationKeyInfo": "Obtenga la clave de integración API genérica para el servicio en este formato \"aaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee\", generalmente el valor del parámetro token de la URL copiada.",
"Topic": "Tema",
"matrix": "Matrix",
"Feishu WebHookUrl": "WebHookURL de Feishu",
"wayToGetPagerDutyKey": "Puede obtener esto yendo a Servicio -> Directorio de servicios -> (Seleccione un servicio) -> Integraciones -> Agregar integración. Aquí puede buscar \"API de eventos V2\". Más información {0}",
"alertaApiKey": "Clave API",
"alertaAlertState": "Estado de Alerta",
"alertaRecoverState": "Estado de Recuperación",
"serwersms": "SerwerSMS.pl",
"serwersmsAPIUser": "Nombre de usuario de API (inc. webapi_ prefix)",
"smseagleGroup": "Nombre(s) de grupo de Guía Telefónica",
"Unpin": "Quitar de destacados",
"Prefix Custom Message": "Prefijo personalizado",
"markdownSupported": "Soporta sintaxis Markdown",
"Server Address": "Dirección del Servidor",
"Learn More": "Aprende Más",
"Pick a RR-Type...": "Seleccione un Tipo RR",
"onebotHttpAddress": "Dirección HTTP OneBot",
"SendKey": "SendKey",
"octopushAPIKey": "\"Clave API\" de las credenciales HTTP API en el panel de control",
"octopushLogin": "\"Inicio de Sesión\" a partir de las credenciales API HTTP en el panel de control"
}

@ -154,7 +154,7 @@
"Token": "توکن",
"Show URI": "نمایش آدرس (URI) ",
"Tags": "برچسب‌ها",
"Add New below or Select...": "یک مورد جدید اضافه کنید و یا از لیست انتخاب کنید...",
"Add New below or Select...": "یک مورد جدید اضافه کنید و یا از لیست انتخاب کنید",
"Tag with this name already exist.": "یک برچسب با این «نام» از قبل وجود دارد",
"Tag with this value already exist.": "یک برچسب با این «مقدار» از قبل وجود دارد.",
"color": "رنگ",
@ -187,5 +187,15 @@
"One record": "یک مورد",
"Info": "اطلاعات",
"Powered by": "نیرو گرفته از",
"apprise": "Apprise (Support 50+ Notification services)"
"apprise": "Apprise (Support 50+ Notification services)",
"Monitor": "مانیتور | مانتیور ها",
"Help": "کمک",
"Game": "بازی",
"Primary Base URL": "آدرس URL اصلی",
"Passive Monitor Type": "حالت مانیتور غیرفعال",
"Specific Monitor Type": "حالت مانیتور شخصی",
"statusMaintenance": "در دست تعمیر",
"Maintenance": "در حال تعمیر",
"General Monitor Type": "حالت مانیتور عمومی",
"markdownSupported": "شیوه نگارشی Markdown پشتیبانی می شود"
}

@ -0,0 +1,699 @@
{
"Dashboard": "Kojetaulu",
"Help": "Apua",
"New Update": "Uusi Päivitys",
"Language": "Kieli",
"Appearance": "Ulkonäkö",
"Theme": "Teema",
"General": "Yleinen",
"Game": "Peli",
"Version": "Versio",
"List": "Lista",
"Add": "Lisää",
"Add New Monitor": "Lisää uusi seurain",
"Quick Stats": "Nopeat tilastot",
"Up": "Ylös",
"Down": "Alas",
"Pending": "Odottaa",
"statusMaintenance": "Huolto",
"Maintenance": "Huolto",
"Unknown": "Tuntematon",
"General Monitor Type": "Yleinen seuranta tyyppi",
"Passive Monitor Type": "Passiivinen seuranta tyyppi",
"markdownSupported": "Markdown-syntaksi tuettu",
"pauseDashboardHome": "Tauko",
"Pause": "Tauko",
"Name": "Nimi",
"Status": "Tila",
"DateTime": "Päivämäärä",
"Message": "Viesti",
"No important events": "Ei tärkeitä tapahtumia",
"Resume": "Jatka",
"Edit": "Muokkaa",
"Delete": "Poista",
"Current": "Nykyinen",
"Uptime": "Päälläoloaika",
"Monitor": "Seurain | Seuraimet",
"day": "Päivä | Päivää",
"-day": "-päivä",
"hour": "Tunti",
"-hour": "-tunti",
"Response": "Vastaus",
"Ping": "Signaali",
"Monitor Type": "Seurain tyyppi",
"Keyword": "Avainsana",
"URL": "URL",
"Hostname": "Isäntänimi",
"Heartbeat Interval": "Sydämensyke intervalli",
"Retries": "Uusintayrityksiä",
"Resend Notification if Down X times consequently": "Uudelleen lähetä ilmoitus jos ei vastausta X määrä peräkkäin",
"Advanced": "Edistynyt",
"checkEverySecond": "Tarkista jokainen {0} sekuntti",
"retryCheckEverySecond": "Yritä uudelleen jokainen {0} sekuntti",
"resendEveryXTimes": "Uudelleen lähetä jokainen {0} kerta",
"ignoreTLSError": "Älä huomioi TLS/SSL virhettä HTTPS nettisivuilla",
"upsideDownModeDescription": "Pyöräytä tila ylösalaisin. Jos palvelu on saavutettavissa, merkitse se SAMMUNEEKSI.",
"maxRedirectDescription": "Maksimi määrä uudelleen ohjauksia joita seurata. Aseta 0 estääksesi uudelleenohjaukset.",
"Upside Down Mode": "Ylösalaisin-moodi",
"Max. Redirects": "Maksimi määrä uudelleenohjauksia",
"Accepted Status Codes": "Sallitut tila koodit",
"Push URL": "Työnnä URL",
"Save": "Tallenna",
"Notifications": "Ilmoitukset",
"Setup Notification": "Määritä ilmoitukset",
"Light": "Vaalea",
"Dark": "Tumma",
"Auto": "Automaattinen",
"Theme - Heartbeat Bar": "Teema - Sydänlyönti palkki",
"Normal": "Normaali",
"Bottom": "Pohja",
"None": "Ei mitään",
"Timezone": "Aikavyöhyke",
"Search Engine Visibility": "Hakukone näkyvyys",
"Allow indexing": "Salli indeksointi",
"Change Password": "Vaihda salasana",
"Current Password": "Nykyinen salasana",
"New Password": "Uusi salasana",
"Repeat New Password": "Toista uusi salasana",
"Update Password": "Päivätä salasana",
"Disable Auth": "Poista todennus käytöstä",
"Enable Auth": "Ota todennus käyttöön",
"Logout": "Kirjaudu ulos",
"Leave": "Poistu",
"I understand, please disable": "Ymmärrän, poista käytöstä",
"Confirm": "Hyväksy",
"Yes": "Kyllä",
"No": "Ei",
"Username": "Käyttäjänimi",
"Password": "Salasana",
"Login": "Kirjaudu",
"add one": "Lisää yksi",
"Notification Type": "Ilmoitus tyyppi",
"Email": "Sähköposti",
"Test": "Testi",
"Certificate Info": "Sertifikaatti tiedot",
"Settings": "Asetukset",
"Check Update On GitHub": "Tarkista päivitys GitHub:ssa",
"Specific Monitor Type": "Tietty seuranta tyyppi",
"Cert Exp.": "Sertifikaatti vanh.",
"Friendly Name": "Ystävällinen nimi",
"Port": "Portti",
"Heartbeat Retry Interval": "Sydämensyke uudelleen yritys intervalli",
"resendDisabled": "Uudelleen lähetys poissa käytöstä",
"retriesDescription": "Maksimi määrä uudelleen yrityksiä ennen kuin palvelu merkitään sammuneeksi ja ilmoitus lähetetään",
"Discourage search engines from indexing site": "Estä hakukoneita indeksoimasta sivua",
"disableauth.message1": "Oletko varma että haluat <strong>poistaa todennuksen käytöstä</strong>?",
"Please use this option carefully!": "Käytä tätä vaihtoehtoa varoen!",
"Remember me": "Muista minut",
"languageName": "Suomi",
"Primary Base URL": "Ensisijainen perus-URL-osoite",
"pushOptionalParams": "Valinnaiset parametrit: {0}",
"Not available, please setup.": "Ei saatavilla, määritä ensin.",
"needPushEvery": "Sinun pitäisi kutsua tätä URL joka {0} sekuntti.",
"disableauth.message2": "Se on suunniteltu tilanteisiin <strong>jossa aiot käyttää kolmannen osapuolen todennnusta</strong> Uptime Kuma:n edessä, kuten Cloudflare Access, Authelia tai jotain muuta todennus mekanismia.",
"No Monitors, please": "Ei seuraimia, kiitos",
"Resolver Server": "Ratkaisija palvelin",
"Resource Record Type": "Resusrssi tallenne tyyppi",
"Last Result": "Viimeinen tulos",
"Create your admin account": "Luo sinun järjestelmänvalvoja käyttäjä",
"Repeat Password": "Toista salasana",
"Import Backup": "Tuo varmuuskopio",
"Export Backup": "Vie varmuuskopio",
"Export": "Vie",
"Import": "Tuo",
"respTime": "Vast. aika (ms)",
"notAvailableShort": "Ei käytössä",
"Default enabled": "Oletus käytössä",
"Apply on all existing monitors": "Aseta jokaiselle olemassa olevaan seuraimeen",
"Create": "Luo",
"Clear Data": "Tyhjennä data",
"Events": "Tapahtumat",
"Heartbeats": "Sydämensyke",
"Auto Get": "Automaattinen haku",
"Schedule maintenance": "Ajoita huolto",
"Affected Monitors": "Vaikutetut seuraimet",
"Pick Affected Monitors...": "Poimi vaikutetut seuraimet…",
"Start of maintenance": "Huollon aloitus",
"All Status Pages": "Kaikki tilanne sivut",
"Select status pages...": "Valitse tilanne sivu…",
"alertNoFile": "Valitse tuotava tiedosto.",
"alertWrongFileType": "Valitse JSON tiedosto.",
"Clear all statistics": "Tyhjennä kaikki tilastot",
"Skip existing": "Ohita olemassa oleva",
"Overwrite": "Päälle kirjoita",
"Options": "Vaihtoehdot",
"Keep both": "Pidä molemmat",
"Verify Token": "Vahvista tunnus",
"Setup 2FA": "Määritä 2FA",
"Enable 2FA": "Ota 2FA käyttöön",
"Disable 2FA": "Poista 2FA käytöstä",
"2FA Settings": "2FA asetukset",
"Two Factor Authentication": "kaksivaiheinen tunnistautuminen",
"Active": "Aktiivinen",
"Token": "Tokeni",
"Show URI": "Näytä URI",
"Tags": "Tunnisteet",
"Tag with this name already exist.": "Tunniste tällä nimellä on jo olemassa.",
"Tag with this value already exist.": "Tunniste tällä arvolla on jo olemassa.",
"color": "Väri",
"value (optional)": "Arvo (valinnainen)",
"Gray": "Harmaa",
"Red": "Punainen",
"Orange": "Oranssi",
"Green": "Vihreä",
"Indigo": "Indigo",
"Purple": "Purppura",
"Pink": "Vaaleanpunainen",
"Custom": "Mukautettu",
"Search...": "Etsi…",
"Avg. Ping": "kesk.arv. viive",
"Entry Page": "Sisääntulosivu",
"statusPageNothing": "Täällä ei ole mitään. Lisää ryhmä tai seurain.",
"No Services": "Ei palveluita",
"Partially Degraded Service": "Osittain heikentynyt palvelu",
"Degraded Service": "Heikentynyt palvelu",
"Add Group": "Lisää ryhmä",
"Add a monitor": "Lisää seurain",
"Edit Status Page": "Muokkaa tilanne sivua",
"Go to Dashboard": "Mene kojelaudalle",
"Status Page": "Tilanne sivu",
"Status Pages": "Tilanne sivut",
"here": "täällä",
"Required": "Vaadittu",
"webhook": "Webhookki",
"Post URL": "Lähetys URL",
"Content Type": "Sisältö tyyppi",
"webhookJsonDesc": "{0} on hyvä jokaisille modernilleille HTTP palvelimille kuten Express.js",
"webhookAdditionalHeadersTitle": "Lisä otsakkeet",
"webhookAdditionalHeadersDesc": "Asettaa lisäpäätteet, jotka on lähetetty webhookilla.",
"Webhook URL": "Webhookin URL",
"Application Token": "Sovellus tokeni",
"Server URL": "Palvelin URL",
"Priority": "Prioriteetti",
"emojiCheatSheet": "Emoji lunttilappu: {0}",
"Read more": "Lue lisää",
"appriseInstalled": "Apprise on asennettu.",
"appriseNotInstalled": "Apprisea ei ole asennettu. {0}",
"Method": "Menetelmä",
"Body": "Runko",
"Headers": "Otsikot",
"PushUrl": "Työntö URL",
"BodyInvalidFormat": "Pyynnön runko ei ole kelvollinen JSON: ",
"Monitor History": "Seuraa historiaa",
"PasswordsDoNotMatch": "Salasanat eivät täsmää.",
"records": "tallenteet",
"One record": "Yksi tallenne",
"Current User": "Nykyinen käyttäjä",
"topic": "Aihe",
"topicExplanation": "MQTT seurattava aihe",
"successMessage": "Onnistumis viesti",
"successMessageExplanation": "MQTT-viesti, jota pidetään onnistuneena",
"recent": "Viimeaikainen",
"Done": "Tehty",
"Info": "Tiedot",
"Security": "Turvallisuus",
"Steam API Key": "Steam API-avain",
"Shrink Database": "Pienennä tietokanta",
"Pick a RR-Type...": "Valitse RR-tyyppi…",
"Pick Accepted Status Codes...": "Valitse hyväksytyt tilakoodit…",
"Default": "Oletus",
"HTTP Options": "HTTP-asetukset",
"Create Incident": "Luo tapaus",
"Title": "Otsikko",
"Content": "Sisältö",
"Style": "Tyyli",
"info": "Tiedot",
"warning": "Varoitus",
"danger": "vaara",
"error": "virhe",
"critical": "kriittinen",
"primary": "ensisijainen",
"dark": "Tumma",
"Post": "Lähetä",
"Please input title and content": "Syötä otsikko ja sisältö",
"Created": "Luo",
"Last Updated": "Viimeksi päivitetty",
"Unpin": "Irroita",
"Switch to Dark Theme": "Vaihda tummaan teemaan",
"Show Tags": "Näytä tunnisteet",
"Hide Tags": "Piilota tunnisteet",
"Description": "Kuvaus",
"No monitors available.": "Ei seuraimia saatavilla.",
"Add one": "Lisää yksi",
"No Monitors": "Ei seuraimia",
"Untitled Group": "Nimetön ryhmä",
"Services": "Palvelut",
"Discard": "Hävitä",
"Cancel": "Peruuttaa",
"Customize": "Mukauta",
"Custom Footer": "Mukautettu alatunniste",
"Custom CSS": "Mukautettu CSS",
"deleteStatusPageMsg": "Haluatko varmasti poistaa tämän tilasivun?",
"Proxies": "Välityspalvelimet",
"default": "Oletus",
"enabled": "Käytössä",
"setAsDefault": "Oletusasetuksena",
"deleteProxyMsg": "Haluatko varmasti poistaa tämän välityspalvelimen kaikista seuraimista?",
"proxyDescription": "Välityspalvelimet on määritettävä seuraimelle toimiakseen.",
"enableProxyDescription": "Tämä välityspalvelin ei vaikuta valvontapyyntöihin ennen kuin se on aktivoitu. Voit hallita välityspalvelimen väliaikaista poistamista käytöstä kaikista seuraimista aktivointitilan perusteella.",
"setAsDefaultProxyDescription": "Tämä välityspalvelin on oletuksena käytössä uusissa seuraimissa. Voit silti poistaa välityspalvelimen käytöstä erikseen jokaisesta seuraimesta.",
"Certificate Chain": "Sertifikaattiketju",
"Valid": "Voimassa oleva",
"Invalid": "Pätemätön",
"User": "Käyttäjä",
"Installed": "Asennettu",
"Not installed": "Ei asennettu",
"Running": "Käynnissä",
"Not running": "Ei käynnissä",
"Remove Token": "Poista token",
"Start": "Käynnistä",
"Stop": "Pysäytä",
"Add New Status Page": "Lisää uusi tilasivu",
"Slug": "Slug",
"startOrEndWithOnly": "Aloita tai lopeta vain {0}",
"No consecutive dashes": "Ei peräkkäisiä viivoja",
"Next": "Seuraava",
"No Proxy": "Ei välityspalvelinta",
"Authentication": "Todennus",
"HTTP Basic Auth": "HTTP-perustodennus",
"Page Not Found": "Sivua ei löydetty",
"Reverse Proxy": "Käänteinen välityspalvelin",
"Backup": "Varmuuskopio",
"About": "Tietoja",
"cloudflareWebsite": "Cloudflare verkkosivusto",
"Message:": "Viesti:",
"Don't know how to get the token? Please read the guide:": "Etkö tiedä kuinka saada tunnus? Ole hyvä ja lue opas:",
"HTTP Headers": "HTTP-otsikot",
"Trust Proxy": "Luota välityspalvelimeen",
"Other Software": "Muut ohjelmistot",
"For example: nginx, Apache and Traefik.": "Esimerkiksi: nginx, Apache ja Traefik.",
"Please read": "Ole hyvä ja lue",
"Subject:": "Aihe:",
"Valid To:": "Voimassa:",
"Days Remaining:": "Päiviä jäljellä:",
"Issuer:": "Myöntäjä:",
"Fingerprint:": "Sormenjälki:",
"No status pages": "Ei tilasivuja",
"Domain Name Expiry Notification": "Verkkotunnuksen vanhenemisilmoitus",
"Proxy": "Välityspalvelin",
"Date Created": "Luomis päivämäärä",
"Footer Text": "Alatunnisteen teksti",
"Show Powered By": "Näytä \"voimanlähteenä\"",
"Domain Names": "Verkkotunnus nimet",
"signedInDisp": "Kirjautunut sisään käyttäjänä {0}",
"signedInDispDisabled": "Todennus poistettu käytöstä.",
"RadiusSecretDescription": "Asiakkaan ja palvelimen välinen yhteinen salaisuus",
"RadiusCalledStationIdDescription": "Kutsutun laitteen tunniste",
"RadiusCallingStationId": "Kutsuaseman tunnus",
"Certificate Expiry Notification": "Varmenteen vanhenemisilmoitus",
"API Username": "API-käyttäjänimi",
"API Key": "API-avain",
"Show update if available": "Näytä päivitys, jos saatavilla",
"Also check beta release": "Tarkista myös betaversio",
"Using a Reverse Proxy?": "Käytätkö käänteistä välityspalvelinta?",
"The slug is already taken. Please choose another slug.": "Slug on jo otettu. Ole hyvä ja valitse toinen slug.",
"RadiusSecret": "Radius Secret",
"RadiusCalledStationId": "Kutsuttu aseman tunnus",
"Steam Game Server": "Steam pelipalvelin",
"Most likely causes:": "todennäköisimmät syyt:",
"The resource is no longer available.": "Resurssi ei ole enää saatavilla.",
"There might be a typing error in the address.": "Osoitteessa saattaa olla kirjoitusvirhe.",
"What you can try:": "Mitä voit kokeilla:",
"Retype the address.": "Kirjoita osoite uudelleen.",
"Go back to the previous page.": "Palaa edelliselle sivulle.",
"Coming Soon": "Tulossa pian",
"Connection String": "Yhteysmerkkijono",
"Query": "Tiedustelu",
"settingsCertificateExpiry": "TLS-sertifikaatin vanheneminen",
"certificationExpiryDescription": "HTTPS-seuraimet käynnistävät ilmoituksen, kun TLS-varmenne vanhenee:",
"Setup Docker Host": "Asenna Docker-isäntä",
"Connection Type": "Yhteystyyppi",
"tcp": "TCP / HTTP",
"Docker Container": "Docker-kontti",
"Container Name / ID": "Säilön nimi/tunnus",
"Docker Host": "Docker-isäntä",
"Docker Hosts": "Docker-isännät",
"Domain": "Verkkotunnus",
"Workstation": "Työasema",
"socket": "kanta",
"Packet Size": "Paketin koko",
"telegram": "Telegram",
"ZohoCliq": "ZohoCliq",
"Bot Token": "Botti tokeni",
"wayToGetTelegramToken": "Voit saada tunnuksen osoitteesta {0}.",
"Chat ID": "Chat-tunnus",
"wayToGetTelegramChatID": "Saat chat-tunnuksesi lähettämällä viestin botille ja siirtymällä tähän URL-osoitteeseen nähdäksesi chat_id:",
"YOUR BOT TOKEN HERE": "BOT TOKENISI TÄHÄN",
"chatIDNotFound": "Chat ID:tä ei löydy; lähetä ensin viesti tälle botille",
"disableCloudflaredNoAuthMsg": "Olet No Auth -tilassa, salasanaa ei tarvita.",
"trustProxyDescription": "Luota \"X-Forwarded-*\"-otsikoihin. Jos haluat saada oikean asiakas-IP:n ja Uptime Kumasi on välityspalvelimen, kuten Nginx tai Apache, takana, sinun tulee ottaa tämä käyttöön.",
"wayToGetLineNotifyToken": "Voit saada käyttötunnuksen osoitteesta {0}",
"Examples": "Esimerkkejä",
"Home Assistant URL": "Home Assistantin URL-osoite",
"Long-Lived Access Token": "Pitkäikäinen pääsytunnus",
"Long-Lived Access Token can be created by clicking on your profile name (bottom left) and scrolling to the bottom then click Create Token. ": "Pitkäikäinen pääsytunnus voidaan luoda napsauttamalla profiilisi nimeä (vasemmalla alareunassa) ja vierittämällä alas ja napsauttamalla sitten Luo tunnus. ",
"Notification Service": "Ilmoituspalvelu",
"default: notify all devices": "oletus: Ilmoita kaikille laitteille",
"A list of Notification Services can be found in Home Assistant under \"Developer Tools > Services\" search for \"notification\" to find your device/phone name.": "Luettelo ilmoituspalveluista löytyy Home Assistantin kohdasta \"Kehittäjätyökalut > Palvelut\". Hae hakusanalla \"ilmoitus\" löytääksesi laitteesi/puhelimesi nimen.",
"Automations can optionally be triggered in Home Assistant:": "Automaatiot voidaan vaihtoehtoisesti laukaista Home Assistantissa:",
"Trigger type:": "Triggerin tyyppi:",
"Event type:": "Tapahtumatyyppi:",
"Frontend Version": "Käyttöliittymän versio",
"Frontend Version do not match backend version!": "Käyttöliittymän versio ei vastaa taustaversiota!",
"backupRecommend": "Varmuuskopioi asema tai tietokansio (./data/) suoraan sen sijaan.",
"Optional": "Vapaaehtoinen",
"squadcast": "Squadcast",
"or": "tai",
"recurringInterval": "Aikaväli",
"Recurring": "Toistuva",
"strategyManual": "Aktiivinen/ei-aktiivinen manuaalisesti",
"warningTimezone": "Se käyttää palvelimen aikavyöhykettä",
"weekdayShortMon": "Ma",
"weekdayShortTue": "Ti",
"weekdayShortWed": "Ke",
"weekdayShortThu": "To",
"weekdayShortFri": "Pe",
"weekdayShortSat": "La",
"weekdayShortSun": "Su",
"dayOfWeek": "Viikonpäivä",
"dayOfMonth": "Kuukauden päivä",
"lastDay": "Viimeinen päivä",
"lastDay1": "Kuukauden viimeinen päivä",
"lastDay2": "Kuukauden toiseksi viimeinen päivä",
"lastDay3": "Kuukauden 3. viimeinen päivä",
"No Maintenance": "Ei huoltoa",
"pauseMaintenanceMsg": "Haluatko varmasti keskeyttää?",
"maintenanceStatus-under-maintenance": "Huollossa",
"maintenanceStatus-inactive": "Epäaktiivinen",
"maintenanceStatus-scheduled": "Aikataulutettu",
"maintenanceStatus-ended": "Päättyi",
"maintenanceStatus-unknown": "Tuntematon",
"Display Timezone": "Näytä aikavyöhyke",
"Server Timezone": "Palvelimen aikavyöhyke",
"statusPageMaintenanceEndDate": "Loppu",
"Enable": "Ota käyttöön",
"Disable": "Poista käytöstä",
"Single Maintenance Window": "Yksi huoltoikkuna",
"Maintenance Time Window of a Day": "Päivän huoltoaikaikkuna",
"Effective Date Range": "Voimassa oleva ajanjakso",
"Schedule Maintenance": "Ajoita huolto",
"Date and Time": "Päivämäärä ja aika",
"DateTime Range": "Päivämäärä-aika-alue",
"loadingError": "Tietoja ei voi noutaa, yritä myöhemmin uudelleen.",
"plugin": "Lisäosa | Lisäosat",
"install": "Asenna",
"installing": "Asennetaan",
"uninstall": "Poista asennus",
"uninstalling": "Poistetaan asennusta",
"smtp": "Sähköposti (SMTP)",
"secureOptionNone": "Ei mitään / STARTTLS (25 587)",
"secureOptionTLS": "TLS (465)",
"Ignore TLS Error": "Ohita TLS-virhe",
"From Email": "Sähköpostista",
"emailCustomSubject": "Mukautettu aihe",
"To Email": "Sähköpostiin",
"smtpCC": "CC",
"smtpBCC": "BCC",
"Discord Webhook URL": "Discord Webhookin URL-osoite",
"Bot Display Name": "Botin näyttönimi",
"Prefix Custom Message": "Mukautetun viestin etuliite",
"Hello @everyone is...": "Hei {'@'}kaikki ovat…",
"wayToGetTeamsURL": "Voit oppia luomaan webhookin URL-osoitteen {0}.",
"wayToGetZohoCliqURL": "Voit oppia luomaan webhookin URL-osoitteen {0}.",
"wayToCheckSignalURL": "Voit tarkistaa tämän URL-osoitteen nähdäksesi, kuinka se määritetään:",
"Number": "Numero",
"Recipients": "Vastaanottajat",
"Access Token": "Käyttöoikeustunnus",
"Channel access token": "Kanavan käyttöoikeustunnus",
"Basic Settings": "Perus asetukset",
"User ID": "käyttäjätunnus",
"Messaging API": "Viestintä API",
"Line Developers Console": "Line Developers Console",
"lineDevConsoleTo": "Line Developers Console - {0}",
"dataRetentionTimeError": "Säilytysajan on oltava 0 tai suurempi",
"infiniteRetention": "Aseta arvoon 0, jos haluat loputtoman säilytyksen.",
"confirmDeleteTagMsg": "Haluatko varmasti poistaa tämän tunnisteen? Tähän tunnisteeseen liittyviä näyttöjä ei poisteta.",
"enableGRPCTls": "Salli lähettää gRPC-pyyntö TLS-yhteydellä",
"grpcMethodDescription": "Menetelmän nimi muunnetaan cammelCase-muotoon, kuten sayHello, check jne.",
"acceptedStatusCodesDescription": "Valitse tilakoodit, jotka katsotaan onnistuneeksi vastaukseksi.",
"deleteMonitorMsg": "Haluatko varmasti poistaa tämän seuraimen?",
"deleteMaintenanceMsg": "Haluatko varmasti poistaa tämän huollon?",
"deleteNotificationMsg": "Haluatko varmasti poistaa tämän ilmoituksen kaikista seuraimista?",
"dnsPortDescription": "DNS-palvelimen portti. Oletusarvo on 53. Voit vaihtaa porttia milloin tahansa.",
"rrtypeDescription": "Valitse valvottava RR-tyyppi",
"pauseMonitorMsg": "Haluatko varmasti keskeyttää?",
"clearHeartbeatsMsg": "Haluatko varmasti poistaa kaikki tämän seuraimen sydämenlyönnit?",
"confirmImportMsg": "Haluatko varmasti tuoda varmuuskopion? Varmista, että olet valinnut oikean tuontivaihtoehdon.",
"twoFAVerifyLabel": "Anna tunnuksesi vahvistaaksesi 2FA:",
"tokenValidSettingsMsg": "Token on voimassa! Voit nyt tallentaa 2FA-asetukset.",
"confirmEnableTwoFAMsg": "Haluatko varmasti ottaa 2FA:n käyttöön?",
"confirmDisableTwoFAMsg": "Haluatko varmasti poistaa 2FA:n käytöstä?",
"recurringIntervalMessage": "Juokse kerran päivässä | Suorita kerran {0} päivässä",
"affectedMonitorsDescription": "Valitse seuraimet, joihin nykyinen huolto vaikuttaa",
"affectedStatusPages": "Näytä tämä huoltoviesti valituilla tilasivuilla",
"atLeastOneMonitor": "Valitse vähintään yksi seurain, johon vaikuttaa",
"notificationDescription": "Ilmoitukset on määritettävä seuraimelle toimiakseen.",
"keywordDescription": "Hae avainsanaa tavallisessa HTML- tai JSON-vastauksessa. Haussa kirjainkoolla on merkitystä.",
"backupDescription": "Voit varmuuskopioida kaikki näytöt ja ilmoitukset JSON-tiedostoon.",
"backupDescription2": "Huomaa: historia- ja tapahtumatiedot eivät sisälly.",
"octopushLogin": "\"Kirjaudu\" ohjauspaneelin HTTP API -tunnistetiedoista",
"promosmsLogin": "API-kirjautumisnimi",
"promosmsPassword": "API-salasana",
"pushoversounds pushover": "Työnnä yli (oletus)",
"pushoversounds bike": "Pyörä",
"pushoversounds bugle": "Merkkitorvi",
"pushoversounds cashregister": "Kassakone",
"pushoversounds classical": "Klassinen",
"pushoversounds cosmic": "Kosminen",
"pushoversounds falling": "Putoaminen",
"pushoversounds gamelan": "Gamelan",
"pushoversounds incoming": "Saapuva",
"pushoversounds intermission": "Väliaika",
"pushoversounds magic": "Taika",
"pushoversounds mechanical": "Mekaaninen",
"pushoversounds pianobar": "Piano Baari",
"pushoversounds spacealarm": "Avaruushälytys",
"pushoversounds tugboat": "Hinaaja",
"pushoversounds alien": "Avaruusolio hälytys (pitkä)",
"pushoversounds climb": "Kiipeily (pitkä)",
"pushoversounds persistent": "Pysyvä (pitkä)",
"pushoversounds updown": "Ylös Alas (pitkä)",
"pushoversounds vibrate": "Vain värinä",
"pushoversounds none": "Ei mitään (hiljainen)",
"pushyAPIKey": "Salainen API-avain",
"pushyToken": "Laitteen tunnus",
"discord": "Discord",
"teams": "Microsoft Teams",
"signal": "Signal",
"gotify": "Gotify",
"slack": "Slack",
"rocket.chat": "Rocket.Chat",
"pushy": "Päällekäyvä",
"PushByTechulus": "Techuluksen työntö",
"octopush": "Mustekala",
"promosms": "PromoSMS",
"clicksendsms": "ClickSend SMS",
"lunasea": "LunaSea",
"GoogleChat": "Google Chat (vain Google Workspace)",
"Kook": "Kook",
"wayToGetKookGuildID": "Ota 'Kehittäjätila' käyttöön Kook-asetuksissa ja napsauta kiltaa hiiren kakkospainikkeella saadaksesi sen tunnuksen",
"Guild ID": "Killan tunnus",
"line": "Line Messenger",
"mattermost": "Mattermost",
"User Key": "Käyttäjäavain",
"Device": "Laite",
"Message Title": "Viestin otsikko",
"More info on:": "Lisätietoja: {0}",
"pushoverDesc2": "Jos haluat lähettää ilmoituksia eri laitteille, täytä Laite-kenttä.",
"SMS Type": "SMS-tyyppi",
"octopushTypePremium": "Premium (nopea - suositellaan hälytykseen)",
"octopushTypeLowCost": "Alhaiset kustannukset (hidas - joskus operaattori estää)",
"checkPrice": "Tarkista kohteen {0} hinnat:",
"apiCredentials": "API-tunnistetiedot",
"Check octopush prices": "Tarkista octopush hinnat {0}.",
"octopushPhoneNumber": "Puhelinnumero (Intl-muoto, esim.: +33612345678) ",
"octopushSMSSender": "Tekstiviestin lähettäjän nimi: 3-11 aakkosnumeerista merkkiä ja välilyönti (a-zA-Z0-9)",
"LunaSea Device ID": "LunaSea laitetunnus",
"Apprise URL": "Apprise URL-osoite",
"Example:": "Esimerkki: {0}",
"Read more:": "Lue lisää: {0}",
"Status:": "Tila: {0}",
"Strategy": "strategia",
"Free Mobile User Identifier": "Ilmainen mobiilikäyttäjätunnus",
"Enable TLS": "Ota TLS käyttöön",
"Proto Service Name": "Proto-palvelun nimi",
"Proto Method": "Proto-menetelmä",
"Proto Content": "Proto-sisältö",
"Economy": "Talous",
"Lowcost": "Halpa",
"high": "korkea",
"SendKey": "LähetäAvain",
"SMSManager API Docs": "SMSManager API Dokumentointi ",
"Gateway Type": "Yhdyskäytävän tyyppi",
"SMSManager": "SMSManager",
"Base URL": "Perus-URL-osoite",
"goAlertIntegrationKeyInfo": "Hanki yleinen API-integrointiavain palvelulle tässä muodossa \"aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee\" yleensä kopioidun URL-osoitteen tunnusparametrin arvona.",
"goAlert": "GoAlert",
"AccessKeyId": "Pääsyn avaimen tunnus",
"SecretAccessKey": "Pääsyn avaimen salaisuus",
"PhoneNumbers": "PuhelinNumerot",
"TemplateCode": "Mallikoodi",
"SignName": "AllekirjoitusNimi",
"Sms template must contain parameters: ": "Tekstiviestimallin tulee sisältää parametrit: ",
"Bark Group": "Bark ryhmä",
"Bark Sound": "Bark ääni",
"WebHookUrl": "WebHookUrl-osoite",
"SecretKey": "Salainen avain",
"For safety, must use secret key": "Turvallisuuden vuoksi on käytettävä salaista avainta",
"Device Token": "Laitteen tunnus",
"Platform": "Alusta",
"iOS": "iOS",
"Bark Endpoint": "Bark päätepiste",
"Huawei": "Huawei",
"High": "Korkea",
"Topic": "Aihe",
"WeCom Bot Key": "WeCom-bottiavain",
"Setup Proxy": "Asenna välityspalvelin",
"Proxy Protocol": "Välityspalvelinprotokolla",
"Proxy Server": "Välityspalvelin",
"matrix": "Matriisi",
"promosmsTypeFlash": "SMS FLASH - Viesti näkyy automaattisesti vastaanottajan laitteessa. Rajoitettu vain puolalaisille vastaanottajille.",
"promosmsTypeSpeed": "SMS SPEED - Järjestelmän korkein prioriteetti. Erittäin nopea ja luotettava, mutta kallis (noin kaksi kertaa SMS TÄYSI hinta).",
"promosmsPhoneNumber": "Puhelinnumero (puolalaiselle vastaanottajalle voit ohittaa suuntanumerot)",
"promosmsSMSSender": "Tekstiviestin lähettäjän nimi: Esirekisteröity nimi tai jokin oletusasetuksista: InfoSMS, SMS Info, MaxSMS, INFO, SMS",
"promosmsAllowLongSMS": "Salli pitkät tekstiviestit",
"Feishu WebHookUrl": "Feishu WebHookURL-osoite",
"Internal Room Id": "Huoneen sisäinen tunnus",
"Android": "Android",
"Channel Name": "Kanavan nimi",
"Uptime Kuma URL": "Uptime Kuma URL-osoite",
"Icon Emoji": "Ikoni Emoji",
"signalImportant": "TÄRKEÄÄ: Et voi sekoittaa ryhmiä ja numeroita vastaanottajissa!",
"aboutWebhooks": "Lisätietoja Webhooksista osoitteessa: {0}",
"aboutChannelName": "Kirjoita kanavan nimi {0} Kanavan nimi -kenttään, jos haluat ohittaa Webhook-kanavan. Esimerkki: #muu-kanava",
"aboutKumaURL": "Jos jätät Uptime Kuma URL -kentän tyhjäksi, se on oletuksena Project GitHub -sivu.",
"smtpDkimSettings": "DKIM-asetukset",
"smtpDkimDesc": "Katso Nodemailer DKIM {0} -sovelluksen käytöstä.",
"documentation": "dokumentointi",
"smtpDkimDomain": "Verkkotunnus nimi",
"smtpDkimKeySelector": "Näppäinvalitsin",
"smtpDkimPrivateKey": "Yksityinen avain",
"smtpDkimHashAlgo": "Hash-algoritmi (valinnainen)",
"smtpDkimheaderFieldNames": "Allekirjoitettavat otsikkoavaimet (valinnainen)",
"smtpDkimskipFields": "Otsikkonäppäimet, joita ei allekirjoiteta (valinnainen)",
"Integration Key": "Integrointiavain",
"Integration URL": "Integroinnin URL-osoite",
"Auto resolve or acknowledged": "Automaattinen ratkaisu tai kuittaus",
"do nothing": "Älä tee mitään",
"auto acknowledged": "automaattisesti kuitattu",
"auto resolve": "automaattinen ratkaisu",
"gorush": "Gorush",
"alerta": "Alerta",
"alertaApiEndpoint": "API-päätepiste",
"alertaEnvironment": "Ympäristö",
"alertaApiKey": "API-avain",
"alertaRecoverState": "Palautustila",
"serwersms": "SerwerSMS.pl",
"serwersmsAPIUser": "API-käyttäjänimi (sis. webapi_-etuliite)",
"serwersmsAPIPassword": "API-salasana",
"serwersmsPhoneNumber": "Puhelinnumero",
"smseagle": "SMSEagle",
"smseagleTo": "Puhelinnumero(t)",
"smseagleGroup": "Puhelinmuistioryhmän nimi/nimet",
"smseagleContact": "Puhelinmuistion yhteyshenkilön nimet",
"smseagleRecipientType": "Vastaanottajan tyyppi",
"smseagleRecipient": "Vastaanottaja(t) (jos useita, ne on erotettava pilkulla)",
"smseagleToken": "API-käyttöoikeustunnus",
"smseagleUrl": "SMSEagle-laitteesi URL-osoite",
"smseagleEncoding": "Lähetä Unicodena",
"smseaglePriority": "Viestin prioriteetti (0-9, oletus = 0)",
"stackfield": "Stackfield",
"Recipient Number": "Vastaanottajan numero",
"From Name/Number": "Nimestä/numerosta",
"Leave blank to use a shared sender number.": "Jätä tyhjäksi, jos haluat käyttää jaettua lähettäjän numeroa.",
"Octopush API Version": "Octopush API -versio",
"Legacy Octopush-DM": "Legacy Octopush-DM",
"ntfy Topic": "ntfy aihe",
"HomeAssistant": "Home Assistant",
"onebotHttpAddress": "OneBot HTTP-osoite",
"onebotGroupMessage": "Ryhmä",
"onebotPrivateMessage": "Yksityinen",
"onebotUserOrGroupId": "Ryhmä/käyttäjätunnus",
"onebotSafetyTips": "Käyttöoikeustunnus on asetettava turvallisuuden vuoksi",
"PushDeer Key": "PushDeer avain",
"wayToGetClickSendSMSToken": "Voit saada API-käyttäjänimen ja API-avaimen osoitteesta {0}.",
"Custom Monitor Type": "Mukautettu seurain tyyppi",
"Google Analytics ID": "Google Analytics -tunnus",
"Edit Tag": "Muokkaa tunnistetta",
"Server Address": "Palvelimen osoite",
"Learn More": "Lisätietoja",
"Inactive": "Epäaktiivinen",
"Add New below or Select...": "Lisää uusi alapuolella tai valitse…",
"Blue": "Sininen",
"Avg. Response": "Kesk.arv. vastaus",
"All Systems Operational": "Kaikki järjestelmät toiminnassa",
"defaultNotificationName": "Minun {ilmoitus} Hälytys ({numero})",
"webhookFormDataDesc": "{multipart} on hyvä PHP:lle. JSON pitää parsia {decodeFunction} avulla",
"HeadersInvalidFormat": "Pyynnön otsikot eivät ole kelvollisia JSON-tiedostoja: ",
"clearDataOlderThan": "Säilytä seuraimen historiatiedot {0} päivää.",
"steamApiKeyDescription": "Steam peli palveliment valvontaa varten tarvitset Steam Web-API -avaimen. Voit rekisteröidä API-avaimesi täällä: ",
"light": "Vaalea",
"Switch to Light Theme": "Vaihda vaaleaan teemaan",
"Powered by": "Voimanlähteenä",
"shrinkDatabaseDescription": "Käynnistä tietokanta VACUUM SQLitelle. Jos tietokanta on luotu 1.10.0:n jälkeen, AUTO_VACUUM on jo käytössä eikä tätä toimintoa tarvita.",
"Accept characters:": "Hyväksy merkit:",
"New Status Page": "Uusi tilasivu",
"wayToGetCloudflaredURL": "(Lataa cloudflared osoitteesta {0})",
"The current connection may be lost if you are currently connecting via Cloudflare Tunnel. Are you sure want to stop it? Type your current password to confirm it.": "Nykyinen yhteys saattaa katketa, jos muodostat parhaillaan yhteyttä Cloudflare-tunnelin kautta. Haluatko varmasti lopettaa sen? Vahvista se kirjoittamalla nykyinen salasanasi.",
"RadiusCallingStationIdDescription": "Kutsu laitteen tunniste",
"Check how to config it for WebSocket": "Tarkista, kuinka se määritetään WebSocketille",
"Docker Daemon": "Docker taustatoiminta",
"deleteDockerHostMsg": "Haluatko varmasti poistaa tämän docker-isännän kaikista seuraimista?",
"supportTelegramChatID": "Tukee suoraa chattia / ryhmää / kanavan chat-tunnusta",
"Event data:": "Tapahtumatyyppi:",
"Then choose an action, for example switch the scene to where an RGB light is red.": "Valitse sitten toiminto, esimerkiksi vaihda kohtaus sellaiseen, jossa RGB-valo on punainen.",
"backupOutdatedWarning": "Vanhentunut: Koska monia ominaisuuksia lisättiin ja tätä varmuuskopiointitoimintoa ei ole ylläpidetty, se ei voi luoda tai palauttaa täydellistä varmuuskopiota.",
"lastDay4": "Kuukauden 4. viimeinen päivä",
"IconUrl": "Kuvakkeen URL-osoite",
"Enable DNS Cache": "Ota DNS-välimuisti käyttöön",
"dnsCacheDescription": "Se ei ehkä toimi joissakin IPv6-ympäristöissä, poista se käytöstä, jos kohtaat ongelmia.",
"confirmUninstallPlugin": "Haluatko varmasti poistaa tämän laajennuksen?",
"wayToGetDiscordURL": "Saat tämän siirtymällä kohtaan Palvelinasetukset -> Integraatiot -> Näytä Webhookit -> Uusi Webhook",
"needSignalAPI": "Sinulla on oltava signaaliasiakas, jossa on REST API.",
"wayToGetLineChannelToken": "Avaa ensin {0}, luo palveluntarjoaja ja kanava (Viestintä API), sitten saat kanavan käyttö tokenin ja käyttäjätunnuksen yllä mainituista valikon kohdista.",
"Icon URL": "Kuvakkeen URL-osoite",
"aboutIconURL": "Voit ohittaa oletusprofiilikuvan antamalla linkin kuvaan kohdassa \"kuvakeen URL\". Ei käytetä, jos kuvake emoji on asetettu.",
"aboutMattermostChannelName": "Voit ohittaa oletuskanavan, jolle Webhook lähettää viestejä, kirjoittamalla kanavan nimen Kanavan nimi -kenttään. Tämä on otettava käyttöön Mattermost Webhook -asetuksissa. Esimerkki: #muu-kanava",
"resolverserverDescription": "Cloudflare on oletuspalvelin. Voit vaihtaa ratkaisijapalvelinta milloin tahansa.",
"enableDefaultNotificationDescription": "Tämä ilmoitus on oletuksena käytössä uusissa seuraimissa. Voit silti poistaa ilmoituksen käytöstä erikseen jokaiselta seuraimelta.",
"clearEventsMsg": "Haluatko varmasti poistaa kaikki tämän seuraimen tapahtumat?",
"confirmClearStatisticsMsg": "Haluatko varmasti poistaa KAIKKI tilastot?",
"importHandleDescription": "Valitse \"Ohita olemassa oleva\", jos haluat ohittaa jokaisen samannimisen seuraimen tai ilmoituksen. \"Korvaa\" poistaa kaikki olemassa olevat seuraimet ja ilmoitukset.",
"passwordNotMatchMsg": "Toistettu salasana ei täsmää.",
"backupDescription3": "Arkaluonteiset tiedot, kuten ilmoitustunnukset, sisältyvät vientitiedostoon. säilytä vienti turvallisesti.",
"endpoint": "päätepiste",
"octopushAPIKey": "\"API-avain\" ohjauspaneelin HTTP API -tunnistetiedoista",
"pushoversounds siren": "Sireeni",
"pushoversounds echo": "Ylityöntö kaiku (pitkä)",
"pushover": "Ylityöntö",
"apprise": "Apprise (tukee yli 50 ilmoituspalvelua)",
"pushbullet": "Pushbullet",
"wayToGetKookBotToken": "Luo sovellus ja hanki bot-tunnus osoitteessa {0}",
"Notification Sound": "Ilmoitusääni",
"pushoverDesc1": "Hätäprioriteetilla (2) on oletusarvoisesti 30 sekunnin aikakatkaisu uudelleenyritysten välillä, ja se vanhenee 1 tunnin kuluttua.",
"octopushLegacyHint": "Käytätkö Octopushin (2011-2020) vanhaa versiota vai uutta versiota?",
"Free Mobile API Key": "Ilmainen mobiilisovellusliittymäavain",
"You can divide numbers with": "Voit jakaa numerot",
"goAlertInfo": "GoAlert on avoimen lähdekoodin sovellus päivystykseen, automatisoituihin eskalaatioihin ja ilmoituksiin (kuten tekstiviestit tai äänipuhelut). Ota automaattisesti mukaan oikea henkilö, oikealla tavalla ja oikeaan aikaan! {0}",
"Retry": "Yritä uudelleen",
"Proxy server has authentication": "Välityspalvelimella on todennus",
"promosmsTypeEco": "SMS ECO - halpa mutta hidas ja usein ylikuormitettu. Rajoitettu vain puolalaisille vastaanottajille.",
"promosmsTypeFull": "SMS FULL - Premium-tason tekstiviestit, voit käyttää lähettäjän nimeäsi (sinun on rekisteröitävä nimi ensin). Luotettava hälytyksiä varten.",
"matrixHomeserverURL": "Kotipalvelimen URL-osoite (http(s):// ja valinnaisesti portti)",
"matrixDesc1": "Löydät sisäisen huonetunnuksen katsomalla Matrix-asiakasohjelman huoneasetusten lisäosaa. Sen pitäisi näyttää tältä: !QMdRCpUIfLwsfjxye6:home.server.",
"matrixDesc2": "On erittäin suositeltavaa, että luot uuden käyttäjän etkä käytä omaa Matrix-käyttäjätunnustasi, koska se antaa täyden pääsyn tilillesi ja kaikkiin huoneisiin, joihin liityit. Luo sen sijaan uusi käyttäjä ja kutsu se vain siihen huoneeseen, josta haluat saada ilmoituksen. Saat käyttöoikeustunnuksen suorittamalla {0}",
"wayToGetPagerDutyKey": "Saat tämän siirtymällä kohtaan Palvelu -> Palveluhakemisto -> (Valitse palvelu) -> Integraatiot -> Lisää integraatio. Täältä voit etsiä \"Events API V2\". Lisätietoja {0}",
"alertaAlertState": "Varoitustila",
"serwersmsSenderName": "Tekstiviestin lähettäjän nimi (rekisteröity asiakasportaalin kautta)",
"onebotMessageType": "OneBot-viestityyppi"
}

@ -4,7 +4,7 @@
"retryCheckEverySecond": "Réessayer toutes les {0} secondes",
"resendEveryXTimes": "Renvoyez toutes les {0} fois",
"resendDisabled": "Renvoi désactivé",
"retriesDescription": "Nombre d'essais avant que le service ne soit déclaré hors ligne et qu'une notification soit envoyée.",
"retriesDescription": "Nombre d'essais avant que le service ne soit déclaré hors ligne et qu'une notification soit envoyée",
"ignoreTLSError": "Ignorer les erreurs liées au certificat SSL/TLS",
"upsideDownModeDescription": "Si le service est en ligne, il sera alors noté hors ligne et vice-versa.",
"maxRedirectDescription": "Nombre maximal de redirections avant que le service ne soit marqué comme hors ligne.",
@ -23,7 +23,7 @@
"affectedMonitorsDescription": "Sélectionnez les sondes concernées par la maintenance en cours",
"affectedStatusPages": "Afficher ce message de maintenance sur les pages d'état sélectionnées",
"atLeastOneMonitor": "Sélectionnez au moins une sonde concernée",
"passwordNotMatchMsg": "Les mots de passe ne correspondent pas",
"passwordNotMatchMsg": "Les mots de passe ne correspondent pas.",
"notificationDescription": "Une fois ajoutée, vous devez l'activer manuellement dans les paramètres de vos hôtes.",
"keywordDescription": "Le mot clé sera recherché dans la réponse HTML/JSON reçue du site internet.",
"pauseDashboardHome": "En pause",
@ -40,7 +40,7 @@
"confirmClearStatisticsMsg": "Êtes-vous sûr de vouloir supprimer toutes les statistiques ?",
"importHandleDescription": "Choisissez « Ignorer l'existant » si vous voulez ignorer chaque sonde ou notification portant le même nom. L'option « Écraser » supprime toutes les sondes et notifications existantes.",
"confirmImportMsg": "Êtes-vous sûr de vouloir importer la sauvegarde ? Veuillez vous assurer que vous avez sélectionné la bonne option d'importation.",
"twoFAVerifyLabel": "Veuillez saisir votre jeton pour vérifier que le système 2FA fonctionne.",
"twoFAVerifyLabel": "Veuillez saisir votre jeton pour vérifier que le système 2FA fonctionne :",
"tokenValidSettingsMsg": "Le jeton est valide. Vous pouvez maintenant sauvegarder les paramètres de double authentification (2FA).",
"confirmEnableTwoFAMsg": "Êtes-vous sûr de vouloir activer la double authentification (2FA) ?",
"confirmDisableTwoFAMsg": "Êtes-vous sûr de vouloir désactiver la double authentification (2FA) ?",
@ -73,11 +73,11 @@
"Delete": "Supprimer",
"Current": "Actuellement",
"Uptime": "Disponibilité",
"Cert Exp.": "Expiration SSL",
"Cert Exp.": "Expiration SSL.",
"day": "jour | jours",
"-day": " jours",
"-day": "-jour",
"hour": "heure",
"-hour": " heure",
"-hour": "-heure",
"Response": "Temps de réponse",
"Ping": "Ping",
"Monitor Type": "Type de sonde",
@ -89,7 +89,7 @@
"Heartbeat Interval": "Intervalle de vérification",
"Retries": "Essais",
"Heartbeat Retry Interval": "Réessayer l'intervalle de vérification",
"Resend Notification if Down X times consequently": "Renvoyer une notification si hors ligne X fois",
"Resend Notification if Down X times consecutively": "Renvoyer la notification si en panne X fois consécutivement",
"Advanced": "Avancé",
"Upside Down Mode": "Mode inversé",
"Max. Redirects": "Nombre maximum de redirections",
@ -235,7 +235,7 @@
"smtpBCC": "CCI",
"discord": "Discord",
"Discord Webhook URL": "URL vers le webhook Discord",
"wayToGetDiscordURL": "Vous pouvez l'obtenir en allant dans « Paramètres du serveur » -> « Intégrations » -> « Créer un Webhook »",
"wayToGetDiscordURL": "Vous pouvez l'obtenir en allant dans « Paramètres du serveur » -> « Intégrations » -> « Consulter les webhooks» -> « Nouveau Webhook »",
"Bot Display Name": "Nom du robot (affiché)",
"Prefix Custom Message": "Préfixe du message personnalisé",
"Hello @everyone is...": "Bonjour {'@'}everyone il…",
@ -264,7 +264,7 @@
"rocket.chat": "Rocket.chat",
"pushover": "Pushover",
"pushy": "Pushy",
"PushByTechulus": "Push by Techulus",
"PushByTechulus": "Push par Techulus",
"octopush": "Octopush",
"promosms": "PromoSMS",
"clicksendsms": "ClickSend SMS",
@ -292,7 +292,7 @@
"apiCredentials": "Identifiants de l'API",
"octopushLegacyHint": "Voulez-vous utiliser l'ancienne version d'Octopush (2011-2020) ou la nouvelle version ?",
"Check octopush prices": "Vérifier les prix d'Octopush {0}.",
"octopushPhoneNumber": "Numéro de téléphone (format international, ex. : +33612345678)",
"octopushPhoneNumber": "Numéro de téléphone (format international, ex. : +33612345678) ",
"octopushSMSSender": "Nom de l'expéditeur : 3-11 caractères alphanumériques avec espace (a-zA-Z0-9)",
"LunaSea Device ID": "Identifiant d'appareil LunaSea",
"Apprise URL": "URL d'Apprise",
@ -442,7 +442,7 @@
"PhoneNumbers": "Numéros de téléphone",
"TemplateCode": "Modèle de code",
"SignName": "Signature",
"Sms template must contain parameters: ": "Le modèle de SMS doit contenir des paramètres : ",
"Sms template must contain parameters: ": "Le modèle de SMS doit contenir des paramètres : ",
"Bark Endpoint": "Endpoint Bark",
"Bark Group": "Groupe Bark",
"Bark Sound": "Son Bark",
@ -501,7 +501,7 @@
"Days Remaining:": "Jours restants : ",
"Issuer:": "Émetteur : ",
"Fingerprint:": "Empreinte : ",
"No status pages": "Aucune page de statut.",
"No status pages": "Aucune page de statut",
"Domain Name Expiry Notification": "Notification d'expiration du nom de domaine",
"Proxy": "Proxy",
"Date Created": "Date de création",
@ -600,7 +600,7 @@
"Long-Lived Access Token": "Jeton d'accès de longue durée",
"Long-Lived Access Token can be created by clicking on your profile name (bottom left) and scrolling to the bottom then click Create Token. ": "Un jeton d'accès de longue durée peut être créé en cliquant sur le nom de votre profil (en bas à gauche) et en faisant défiler vers le bas, puis cliquez sur Créer un jeton. ",
"Notification Service": "Service de notifications",
"default: notify all devices": "par défaut: notifier tous les appareils",
"default: notify all devices": "par défaut : notifier tous les appareils",
"A list of Notification Services can be found in Home Assistant under \"Developer Tools > Services\" search for \"notification\" to find your device/phone name.": "Une liste des services de notification peut être trouvée dans Home Assistant sous \"Outils de développement > Services\" recherchez \"notification\" pour trouver le nom de votre appareil/téléphone.",
"Automations can optionally be triggered in Home Assistant:": "Les automatisations peuvent éventuellement être déclenchées dans Home Assistant : ",
"Trigger type:": "Type de déclencheur : ",
@ -618,7 +618,7 @@
"Optional": "Optionnel",
"squadcast": "Squadcast",
"SendKey": "SendKey",
"SMSManager API Docs": "Documentations de l'API SMSManager ",
"SMSManager API Docs": "Documentations de l'API SMSManager ",
"Gateway Type": "Type de passerelle",
"SMSManager": "SMSManager",
"You can divide numbers with": "Vous pouvez diviser des nombres avec",
@ -691,5 +691,10 @@
"uninstall": "Désinstaller",
"uninstalling": "Désinstallation",
"confirmUninstallPlugin": "Voulez-vous vraiment désinstaller ce plugin ?",
"Custom Monitor Type": "Type de sonde personnalisé"
"Custom Monitor Type": "Type de sonde personnalisé",
"markdownSupported": "Syntaxe Markdown supportée",
"Google Analytics ID": "Identifiant Google Analytics",
"Server Address": "Adresse du serveur",
"Learn More": "En savoir plus",
"Edit Tag": "Modifier l'étiquette"
}

@ -15,10 +15,10 @@
"statusMaintenance": "תחזוקה",
"Schedule maintenance": "תחזוקה מתוכננת",
"Affected Monitors": "מוניטורים מושפעים",
"Pick Affected Monitors...": "בחר המוניטרים מושפעים...",
"Pick Affected Monitors...": "בחר המוניטריים המושפעים…",
"Start of maintenance": "תחילת תחזוקה",
"All Status Pages": "כל דפי הסטטוס",
"Select status pages...": "בחר דפי סטטוס...",
"Select status pages...": "בחר דפי סטטוס",
"recurringIntervalMessage": "רוץ פעם ביום | הפעל אחת ל-{0} ימים",
"affectedMonitorsDescription": "בחר מוניטורים שמושפעים מהתחזוקה הנוכחית",
"affectedStatusPages": "הצג הודעת תחזוקה זו בדפי סטטוס שנבחרו",
@ -89,7 +89,7 @@
"Heartbeat Interval": "מרווח פעימות",
"Retries": "נסיונות חוזרים",
"Heartbeat Retry Interval": "מרווח נסיונות חוזר של פעימות",
"Resend Notification if Down X times consequently": "שלח שוב הודעה אם ירד X פעמים כתוצאה מכך",
"Resend Notification if Down X times consecutively": "שלח שוב הודעה אם ירד X פעמים כתוצאה מכך",
"Advanced": "מתקדם",
"Upside Down Mode": "מצב הפוך",
"Max. Redirects": "מקסימום הפניות מחדש",
@ -177,7 +177,7 @@
"Token": "אסימון",
"Show URI": "הצג URI",
"Tags": "תגים",
"Add New below or Select...": "הוסף חדש למטה או בחר...",
"Add New below or Select...": "הוסף חדש למטה או בחר",
"Tag with this name already exist.": "תג בשם זה כבר קיים.",
"Tag with this value already exist.": "תג עם ערך זה כבר קיים.",
"color": "צבע",
@ -190,7 +190,7 @@
"Indigo": "כחול כהה",
"Purple": "סגול",
"Pink": "כתום",
"Search...": "לחפש...",
"Search...": "לחפש",
"Avg. Ping": "פינג ממוצע",
"Avg. Response": "ממוצע תגובה",
"Entry Page": "דף כניסה",
@ -237,7 +237,7 @@
"wayToGetDiscordURL": "אתה יכול לקבל זאת על ידי מעבר להגדרות שרת -> אינטגרציות -> צור Webhook",
"Bot Display Name": "שם תצוגה של בוט",
"Prefix Custom Message": "קידומת הודעה מותאמת אישית",
"Hello @everyone is...": "שלום {'@'}כולם...",
"Hello @everyone is...": "שלום {'@'}כולם",
"teams": "Microsoft Teams",
"Webhook URL": "כתובת האתר של Webhook",
"wayToGetTeamsURL": "אתה יכול ללמוד כיצד ליצור כתובת אתר ל-webhook {0}.",
@ -342,8 +342,8 @@
"Security": "אבטחה",
"Steam API Key": "מפתח API Steam",
"Shrink Database": "מסד נתונים מכווץ",
"Pick a RR-Type...": "בחר סוג RR ...",
"Pick Accepted Status Codes...": "בחר קודי סטטוס מקובלים ...",
"Pick a RR-Type...": "בחר סוג RR",
"Pick Accepted Status Codes...": "בחר קודי סטטוס מקובלים",
"Default": "בְּרִירַת מֶחדָל",
"HTTP Options": "אפשרויות HTTP",
"Create Incident": "ליצור אירוע",
@ -587,7 +587,7 @@
"Domain": "תְחוּם",
"Workstation": "עמדת עבודה",
"disableCloudflaredNoAuthMsg": "אתה לא נמצא במצב AUTH, אין צורך בסיסמה.",
"trustProxyDescription": "סמוך על כותרות 'x-forwarded-*'.אם אתה רוצה להשיג את ה- IP של הלקוח הנכון וה- Uptime Kuma שלך מאחור כמו Nginx או Apache, עליך לאפשר זאת.",
"trustProxyDescription": "סמוך על הכותרות 'X-Forwarded-*'. אם אתה רוצה לקבל את כתובת ה-IP של הלקוח וה- Uptime Kuma שלך עומד מאחורי פרוקסי כגון Nginx או Apache, עליך להפעיל זאת.",
"wayToGetLineNotifyToken": "אתה יכול לקבל אסימון גישה מ- {0}",
"Examples": "דוגמאות",
"Home Assistant URL": "כתובת URL עוזרת ביתית",
@ -607,7 +607,7 @@
"goAlertInfo": "SAETRERT הוא יישום קוד פתוח לתזמון שיחה, הסלמות והודעות אוטומטיות (כמו SMS או שיחות קוליות).לעסוק אוטומטית את האדם הנכון, בדרך הנכונה ובזמן הנכון!{0}",
"goAlertIntegrationKeyInfo": "קבל מפתח אינטגרציה של API גנרי לשירות בפורמט זה \"AAAAAAAA-BBB-CCCC-DDDD-EEEEEEEEEEE \" בדרך כלל הערך של פרמטר האסימון של URL שהועתק.",
"goAlert": "GoAlert",
"backupOutdatedWarning": "מיושם: מכיוון שהרבה תכונות שנוספו ותכונת הגיבוי הזו מעט לא מצומצמת, היא לא יכולה לייצר או לשחזר גיבוי שלם.",
"backupOutdatedWarning": "הוצא משימוש: מכיוון שנוספו הרבה תכונות ותכונת הגיבוי הזו קצת לא מתוחזקת, היא לא יכולה ליצור או לשחזר גיבוי מלא.",
"backupRecommend": "אנא גבה את עוצמת הקול או את תיקיית הנתונים (./data/) ישירות במקום.",
"Optional": "אופציונאלי",
"squadcast": "Squadcast",
@ -668,5 +668,29 @@
"high": "גבוהה",
"General Monitor Type": "מוניטור כללי",
"Passive Monitor Type": "מוניטור פסיבי",
"Specific Monitor Type": "סוג מוניטור ספציפי"
"Specific Monitor Type": "סוג מוניטור ספציפי",
"Custom Monitor Type": "סוג צג מותאם אישית",
"Monitor": "מוניטור | מוניטרים",
"promosmsAllowLongSMS": "אפשר SMS ארוך",
"loadingError": "לא ניתן לאחזר את הנתונים, אנא נסה שוב מאוחר יותר.",
"plugin": "תוסף | תוספים",
"install": "להתקין",
"installing": "מתקין",
"uninstall": "הסר את ההתקנה",
"uninstalling": "מסיר התקנה",
"confirmUninstallPlugin": "האם אתה בטוח שברצונך להסיר את התוסף הזה?",
"Help": "עזרה",
"Game": "משחק",
"Packet Size": "גודל חבילה",
"markdownSupported": "תחביר סימון נתמך (Markdown )",
"Custom": "מותאם אישית",
"ZohoCliq": "זוהו קליק",
"wayToGetZohoCliqURL": "אתה יכול ללמוד כיצד ליצור כתובת אתר ל-webhook {0}.",
"dataRetentionTimeError": "תקופת השמירה חייבת להיות 0 או יותר",
"infiniteRetention": "הגדר ל-0 לשמירה אינסופית.",
"confirmDeleteTagMsg": "האם אתה בטוח שברצונך למחוק תג זה? צגים המשויכים לתג זה לא יימחקו.",
"Kook": "קוק",
"wayToGetKookBotToken": "צור יישום וקבל את אסימון הבוט שלך ב-{0}",
"wayToGetKookGuildID": "הפעל את 'מצב מפתח' בהגדרת קוק, ולחץ לחיצה ימנית על הגילדה כדי לקבל את המזהה שלה",
"Guild ID": "מזהה גילד"
}

@ -378,7 +378,7 @@
"resendEveryXTimes": "Ponovno pošalji svakih {0} puta",
"resendDisabled": "Ponovno slanje je onemogućeno",
"dnsPortDescription": "Port DNS poslužitelja. Zadana vrijednost je 53. Moguće je promijeniti ga u svakom trenutku.",
"Resend Notification if Down X times consequently": "Ponovno pošalji obavijest ako je usluga nedostupna više puta zaredom",
"Resend Notification if Down X times consecutively": "Ponovno pošalji obavijest ako je usluga nedostupna više puta zaredom",
"topic": "Tema",
"topicExplanation": "MQTT tema koja će se monitorirati",
"successMessage": "Poruka o uspjehu",

@ -410,5 +410,9 @@
"IconUrl": "Ikon URL",
"successMessage": "Sikeres üzenet",
"lastDay1": "A hónap utolsó napja",
"Guild ID": "Guild ID"
"Guild ID": "Guild ID",
"Help": "Súgó",
"statusMaintenance": "Karbantartás",
"Maintenance": "Karbantartás",
"Game": "Játék"
}

@ -1,7 +1,7 @@
{
"languageName": "Bahasa Indonesia (Indonesian)",
"checkEverySecond": "Cek Setiap {0} detik.",
"retryCheckEverySecond": "Coba lagi setiap {0} detik.",
"checkEverySecond": "Cek Setiap {0} detik",
"retryCheckEverySecond": "Coba lagi setiap {0} detik",
"resendEveryXTimes": "Kirim ulang setiap {0} kali",
"resendDisabled": "Kirim ulang dinonaktifkan",
"retriesDescription": "Percobaan ulang maksimum sebelum layanan dinyatakan tidak aktif dan notifikasi dikirim",
@ -71,10 +71,10 @@
"URL": "URL",
"Hostname": "Hostname",
"Port": "Port",
"Heartbeat Interval": "Jarak Waktu Heartbeat ",
"Heartbeat Interval": "Jarak Waktu Heartbeat",
"Retries": "Coba lagi",
"Heartbeat Retry Interval": "Jarak Waktu Heartbeat Mencoba kembali ",
"Resend Notification if Down X times consequently": "Kirim Ulang Notifikasi jika Tidak Aktif X kali",
"Heartbeat Retry Interval": "Jeda Pengulangan Heartbeat",
"Resend Notification if Down X times consecutively": "Kirim Ulang Notifikasi jika Tidak Aktif X kali",
"Advanced": "Tingkat Lanjut",
"Upside Down Mode": "Mode Terbalik",
"Max. Redirects": "Maksimal Pengalihan",
@ -581,5 +581,14 @@
"goAlertIntegrationKeyInfo": "Dapatkan kunci integrasi API generik untuk layanan dalam format ini \"aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee\" biasanya nilai parameter token dari URL yang disalin.",
"goAlert": "GoAlert",
"backupOutdatedWarning": "Tidak digunakan lagi: Karena banyak fitur ditambahkan dan fitur cadangan ini agak tidak terawat, itu tidak dapat menghasilkan atau memulihkan cadangan lengkap.",
"backupRecommend": "Harap cadangkan volume atau folder data (./data/) secara langsung."
"backupRecommend": "Harap cadangkan volume atau folder data (./data/) secara langsung.",
"Help": "Bantuan",
"Game": "Gim/Permainan",
"markdownSupported": "Dukungan sintaks markdown",
"statusMaintenance": "Pemeliharaan",
"Maintenance": "Pemeliharaan",
"General Monitor Type": "Tipe Monitor Umum",
"Passive Monitor Type": "Tipe Monitor Pasif",
"Specific Monitor Type": "Tipe Monitor Spesifik",
"Monitor": "Monitor"
}

@ -1,15 +1,15 @@
{
"languageName": "Italiano (Italian)",
"checkEverySecond": "controlla ogni {0} secondi",
"retryCheckEverySecond": "Riprova ogni {0} secondi.",
"retriesDescription": "Tentativi prima che il servizio venga marcato come \"DOWN\" e che una notifica venga inviata.",
"ignoreTLSError": "Ignora gli errori TLS/SSL per i siti HTTPS.",
"retryCheckEverySecond": "Riprova ogni {0} secondi",
"retriesDescription": "Tentativi prima che il servizio venga marcato come \"DOWN\" e che una notifica venga inviata",
"ignoreTLSError": "Ignora gli errori TLS/SSL per i siti HTTPS",
"upsideDownModeDescription": "Se il servizio risulta raggiungibile viene marcato come \"DOWN\".",
"maxRedirectDescription": "Numero massimo di redirezionamenti consentito. Per disabilitare, impostare \"0\".",
"acceptedStatusCodesDescription": "Elenco di codici di stato HTTP che sono considerati validi.",
"passwordNotMatchMsg": "La password non corrisponde.",
"notificationDescription": "Assegnare la notifica a uno o più oggetti monitorati per metterla in funzione.",
"keywordDescription": "Cerca la parola chiave nella risposta in html o JSON e fai distinzione tra maiuscole e minuscole",
"keywordDescription": "Cerca la parola chiave nella risposta in HTML o JSON. Distingue tra maiuscole e minuscole.",
"pauseDashboardHome": "In Pausa",
"deleteMonitorMsg": "Sei sicuro di voler eliminare questo oggetto monitorato?",
"deleteNotificationMsg": "Sei sicuro di voler eliminare questa notifica per tutti gli oggetti monitorati?",
@ -28,7 +28,7 @@
"confirmDisableTwoFAMsg": "Sei sicuro di voler disabilitare l'autenticazione a due fattori?",
"Settings": "Impostazioni",
"Dashboard": "Dashboard",
"New Update": "Nuovo aggiornamento disponibile!",
"New Update": "Nuovo aggiornamento disponibile",
"Language": "Lingua",
"Appearance": "Aspetto",
"Theme": "Tema",
@ -55,7 +55,7 @@
"Delete": "Elimina",
"Current": "Corrente",
"Uptime": "Tempo di attività",
"Cert Exp.": "Scadenza certificato",
"Cert Exp.": "Scadenza Certificato",
"day": "giorno | giorni",
"-day": "-giorni",
"hour": "ora",
@ -70,7 +70,7 @@
"Port": "Porta",
"Heartbeat Interval": "Intervallo di controllo",
"Retries": "Tentativi",
"Heartbeat Retry Interval": "Intervallo tra i tentativo di controllo",
"Heartbeat Retry Interval": "Intervallo tra i tentativi di controllo",
"Advanced": "Avanzate",
"Upside Down Mode": "Modalità invertita",
"Max. Redirects": "Reindirizzamenti massimi",
@ -105,7 +105,7 @@
"Please use this option carefully!": "Utilizzare con attenzione!",
"Logout": "Esci",
"Leave": "Annulla",
"I understand, please disable": "Lo capisco, disabilitare l'autenticazione.",
"I understand, please disable": "Lo capisco, disabilitare l'autenticazione",
"Confirm": "Conferma",
"Yes": "Sì",
"No": "No",
@ -114,7 +114,7 @@
"Remember me": "Ricorda credenziali",
"Login": "Accesso",
"No Monitors, please": "Nessun monitor presente,",
"add one": "aggiungine uno!",
"add one": "aggiungine uno",
"Notification Type": "Servizio di notifica",
"Email": "E-mail",
"Test": "Fai una prova",
@ -138,8 +138,8 @@
"Heartbeats": "Controlli",
"Auto Get": "Rileva",
"backupDescription": "È possibile fare il backup di tutti i monitoraggi e di tutte le notifiche in un file JSON.",
"backupDescription2": "NOTA: lo storico e i dati relativi agli eventi non saranno inclusi nel backup",
"backupDescription3": "Dati sensibili come i token di autenticazione saranno inclusi nel backup, custodisci il file in un luogo sicuro!",
"backupDescription2": "NOTA: lo storico e i dati relativi agli eventi non saranno inclusi nel backup.",
"backupDescription3": "Dati sensibili come i token di autenticazione saranno inclusi nel backup, custodisci il file in un luogo sicuro.",
"alertNoFile": "Selezionare il file da importare.",
"alertWrongFileType": "Selezionare un file JSON.",
"Clear all statistics": "Cancella tutte le statistiche",
@ -158,7 +158,7 @@
"Token": "Token",
"Show URI": "Mostra URI",
"Tags": "Etichette",
"Add New below or Select...": "Aggiungi oppure scegli...",
"Add New below or Select...": "Aggiungi oppure scegli",
"Tag with this name already exist.": "Un'etichetta con questo nome già esiste.",
"Tag with this value already exist.": "Un'etichetta con questo valore già esiste.",
"color": "colore",
@ -171,7 +171,7 @@
"Indigo": "Indaco",
"Purple": "Viola",
"Pink": "Rosa",
"Search...": "Cerca...",
"Search...": "Cerca",
"Avg. Ping": "Tempo medio di risposta al ping",
"Avg. Response": "Tempo medio di risposta",
"Entry Page": "Pagina Principale",
@ -193,7 +193,7 @@
"Bot Token": "Token del bot",
"wayToGetTelegramToken": "Puoi ottenere il token da {0}.",
"Chat ID": "ID Chat",
"supportTelegramChatID": "Supporta chat private, gruppi e canali.",
"supportTelegramChatID": "Supporta ID di chat private, gruppi e canali",
"wayToGetTelegramChatID": "È possibile ricereve l'ID chat mandando un messaggio al bot e poi andando in questo URL per visualizzare il chat_id:",
"YOUR BOT TOKEN HERE": "QUI IL TOKEN DEL BOT",
"chatIDNotFound": "Non trovo l'ID chat. Prima bisogna mandare un messaggio al bot",
@ -216,7 +216,7 @@
"wayToGetDiscordURL": "È possibile recuperarlo da Impostazioni server -> Integrazioni -> Creare Webhook",
"Bot Display Name": "Nome del Bot",
"Prefix Custom Message": "Prefisso per il messaggio personalizzato",
"Hello @everyone is...": "Ciao a {'@'}everyone ...",
"Hello @everyone is...": "Ciao a {'@'}everyone ",
"teams": "Microsoft Teams",
"Webhook URL": "URL Webhook",
"wayToGetTeamsURL": "È possibile imparare a creare un URL Webhook {0}.",
@ -287,7 +287,7 @@
"matrix": "Matrix",
"promosmsTypeEco": "SMS ECO - economico, ma lento e spesso sovraccarico. Limitato solamente a destinatari Polacchi.",
"promosmsTypeFlash": "SMS FLASH - Il messaggio sarà automaticamente mostrato sul dispositivo dei destinatari. Limitato solo a destinatari Polacchi.",
"promosmsTypeFull": "SMS FULL - Premium, È possibile utilizzare il proprio come come mittente (è necessario prima registrare il nome). Affidabile per gli allarmi.",
"promosmsTypeFull": "SMS FULL - Premium, È possibile utilizzare il proprio nome come mittente (è necessario prima registrare il nome). Affidabile per gli allarmi.",
"promosmsTypeSpeed": "SMS SPEED - Maggior priorità. Rapido, affidabile, ma costoso (costa il doppio di SMS FULL).",
"promosmsPhoneNumber": "Numero di Telefono (per destinatari Polacchi si può omettere il codice area)",
"promosmsSMSSender": "Mittente SMS : Nome preregistrato oppure uno dei seguenti: InfoSMS, SMS Info, MaxSMS, INFO, SMS",
@ -304,7 +304,7 @@
"BodyInvalidFormat": "Il corpo di richiesta non è un JSON valido: ",
"Monitor History": "Storico monitor",
"clearDataOlderThan": "Mantieni lo storico per {0} giorni.",
"PasswordsDoNotMatch": "Le password non corrispondono!",
"PasswordsDoNotMatch": "Le password non corrispondono.",
"records": "records",
"One record": "One record",
"steamApiKeyDescription": "Per monitorare un server di gioco Steam è necessaria una Web-API Key di Steam. È possibile registrarne una qui: ",
@ -315,8 +315,8 @@
"Security": "Sicurezza",
"Steam API Key": "API Key di Steam",
"Shrink Database": "Comprimi database",
"Pick a RR-Type...": "Scegli un tipo di RR...",
"Pick Accepted Status Codes...": "Scegli i codici di Stato Accettati...",
"Pick a RR-Type...": "Scegli un tipo di RR",
"Pick Accepted Status Codes...": "Scegli i codici di Stato Accettati",
"Default": "Predefinito",
"HTTP Options": "Opzioni HTTP",
"Create Incident": "Segnala incidente",
@ -340,8 +340,8 @@
"Hide Tags": "Nascondi etichette",
"Description": "Descrizione",
"No monitors available.": "Nessun monitor disponibile.",
"Add one": "Aggiungine uno!",
"No Monitors": "Nessun monitor presente.",
"Add one": "Aggiungine uno",
"No Monitors": "Nessun monitor presente",
"Untitled Group": "Gruppo senza titolo",
"Services": "Servizi",
"Discard": "Scarta modifiche",
@ -363,5 +363,58 @@
"smtpDkimHashAlgo": "Algoritmo di hashing (opzionale)",
"smtpDkimheaderFieldNames": "Campi Intestazione da firmare (opzionale)",
"smtpDkimskipFields": "Campi Intestazione da non firmare (opzionale)",
"GoogleChat": "Google Chat (solo per Google Workspace)"
"GoogleChat": "Google Chat (solo per Google Workspace)",
"Help": "Aiuto",
"Maintenance": "Manutenzione",
"statusMaintenance": "In manutenzione",
"General Monitor Type": "Monitor Generico",
"Game": "Gioco",
"Passive Monitor Type": "Monitor Passivo",
"Specific Monitor Type": "Monitor Specifico",
"Monitor": "Monitor | Monitor",
"Topic": "Argomento",
"markdownSupported": "Sintassi markdown supportata",
"Proxy Server": "Server Proxy",
"Select status pages...": "Seleziona pagine di stato…",
"Schedule maintenance": "Pianifica manutenzione",
"Start of maintenance": "Inizio della manutenzione",
"All Status Pages": "Tutte le pagine di stato",
"webhookAdditionalHeadersTitle": "Headers aggiuntivi",
"resendEveryXTimes": "Reinvia ogni {0} volte",
"resendDisabled": "Reinvio disabilitato",
"Resend Notification if Down X times consequently": "Reinvia la notifica se Down X volte di seguito",
"Add New Status Page": "Aggiungi nuova pagina di stato",
"webhookAdditionalHeadersDesc": "Imposta gli header aggiuntivi inviati nel webhook.",
"topicExplanation": "MQTT topic da controllare",
"successMessage": "Messaggio con successo",
"successMessageExplanation": "Messaggio MQTT considerato come successo",
"error": "errore",
"critical": "critico",
"Customize": "Personalizza",
"Custom Footer": "Piè di pagina personalizzato",
"Custom CSS": "CSS personalizzato",
"deleteStatusPageMsg": "Confermi la cancellazione di questa pagina di stato?",
"default": "Predefinito",
"enabled": "Abilitato",
"setAsDefault": "Imposta come predefinito",
"deleteProxyMsg": "Confermi la cancellazione di questo proxy per tutti i monitoraggi?",
"proxyDescription": "I proxy devono essere assegnati ad un monitoraggio per essere operativi.",
"setAsDefaultProxyDescription": "Questo proxy sarà abilitato come predefinito per tutti i nuovi monitoraggi. E' possibile disabilitare il proxy in modo indipendente per ogni singolo monitoraggio.",
"Certificate Chain": "Catena di certificati",
"Invalid": "Non valido",
"User": "Utente",
"Installed": "Installato",
"Not installed": "Non installato",
"Running": "In esecuzione",
"Not running": "Fermo",
"Remove Token": "Rimuovere token",
"Start": "Avvio",
"Next": "Prossimo",
"No Proxy": "Nessun proxy",
"Authentication": "Autenticazione",
"New Status Page": "Nuova pagina di stato",
"Page Not Found": "Pagina non trovata",
"Affected Monitors": "Monitoraggi interessati",
"Pick Affected Monitors...": "Seleziona i monitoraggi interessati…",
"Valid": "Valido"
}

@ -21,7 +21,7 @@
"Language": "言語",
"Appearance": "外観",
"Theme": "テーマ",
"General": "General",
"General": "全般的",
"Version": "バージョン",
"Check Update On GitHub": "GitHubでアップデートを確認する",
"List": "一覧",
@ -167,5 +167,35 @@
"Edit Status Page": "ステータスページ編集",
"Go to Dashboard": "ダッシュボード",
"Status Page": "ステータスページ",
"Status Pages": "ステータスページ"
"Status Pages": "ステータスページ",
"Shrink Database": "データベースの縮小",
"Start": "始める",
"Retry": "リトライ",
"Please read": "読んでください",
"Orange": "橙",
"Gateway Type": "ゲートウェイの種類",
"Game": "ゲーム",
"Help": "ヘルプ",
"Maintenance": "メンテナンス",
"resendDisabled": "再送信不可",
"Schedule maintenance": "メンテナンスのスケジュール",
"Affected Monitors": "影響を受けるモニター",
"Pick Affected Monitors...": "影響を受けるモニターを選択…",
"Start of maintenance": "メンテナンス開始",
"General Monitor Type": "汎用モニタータイプ",
"resendEveryXTimes": "{0}回ごとに再送信",
"markdownSupported": "マークダウン構文がサポートされています",
"All Status Pages": "すべてのステータス ページ",
"Monitor": "モニター |モニター",
"Resend Notification if Down X times consequently": "ダウンX回連続で通知再送",
"Push URL": "プッシュ URL",
"needPushEvery": "{0} 秒ごとにこの URL を呼び出す必要があります。",
"pushOptionalParams": "オプションのパラメーター: {0}",
"disableauth.message1": "<strong>認証を無効</strong>にしてもよろしいですか?",
"disableauth.message2": "これは、Cloudflare Access、Authelia、またはその他の認証メカニズムなど、Uptime Kuma の前に<strong>サードパーティ認証を実装するシナリオ向けに設計されています</strong>。",
"Please use this option carefully!": "このオプションは慎重に使用してください。",
"Primary Base URL": "プライマリ ベース URL",
"statusMaintenance": "メンテナンス",
"Passive Monitor Type": "パッシブモニタータイプ",
"Specific Monitor Type": "特定のモニターの種類"
}

@ -680,7 +680,7 @@
"Passive Monitor Type": "수동 모니터링",
"Specific Monitor Type": "특정 모니터링",
"Monitor": "모니터",
"Resend Notification if Down X times consequently": "X번 중단될 경우 알림 다시 보내기",
"Resend Notification if Down X times consecutively": "X번 중단될 경우 알림 다시 보내기",
"Schedule maintenance": "점검 예약하기",
"Affected Monitors": "영향을 받는 모니터링",
"Pick Affected Monitors...": "영향을 받는 모니터링 선택하기…",

@ -208,7 +208,7 @@
"smtpBCC": "UDW",
"discord": "Discord",
"Discord Webhook URL": "URL webhook Discorda",
"wayToGetDiscordURL": "Możesz go uzyskać, przechodząc do Ustawienia serwera -> Integracje -> Tworzenie webhooka",
"wayToGetDiscordURL": "Możesz go uzyskać, przechodząc do Ustawienia serwera -> Integracje -> Webhooki -> Tworzenie webhooka",
"Bot Display Name": "Wyświetlana nazwa bota",
"Prefix Custom Message": "Własny początek wiadomości",
"Hello @everyone is...": "Hej {'@'}everyone…",
@ -388,8 +388,8 @@
"alertaApiEndpoint": "Punkt końcowy API",
"alertaEnvironment": "Środowisko",
"alertaApiKey": "Klucz API",
"alertaAlertState": "Alert State",
"alertaRecoverState": "Recover State",
"alertaAlertState": "Stan alarmowy",
"alertaRecoverState": "Stan odzyskania",
"deleteStatusPageMsg": "Jesteś pewien, że chcesz usunąć tę stronę statusów?",
"Proxies": "Proxy",
"default": "Domyślny",
@ -402,7 +402,7 @@
"Certificate Chain": "Łańcuch certyfikatów",
"Valid": "Ważny",
"Invalid": "Nieważny",
"AccessKeyId": "AccessKey ID",
"AccessKeyId": "ID klucza dostępu",
"SecretAccessKey": "AccessKey Sekret",
"PhoneNumbers": "Numery telefonów",
"TemplateCode": "Kod szablonu",
@ -494,7 +494,7 @@
"atLeastOneMonitor": "Wybierz co najmniej jeden monitor, którego dotyczy problem",
"deleteMaintenanceMsg": "Czy na pewno chcesz usunąć tę konserwację?",
"dnsPortDescription": "Port serwera DNS. Domyślnie 53. Możesz zmienić port w dowolnym momencie.",
"Resend Notification if Down X times consequently": "Wyślij ponownie powiadomienie, jeśli nie działa X razy pod rząd",
"Resend Notification if Down X times consecutively": "Wyślij ponownie powiadomienie, jeśli nie działa X razy z rzędu",
"error": "błąd",
"critical": "krytyczny",
"wayToGetPagerDutyKey": "Możesz to uzyskać, przechodząc do Service -> Service Directory -> (wybierz usługę) -> Integrations -> Add integration. Tutaj możesz wyszukać \"Events API V2\". Więcej informacji {0}",
@ -508,7 +508,7 @@
"Bark Sound": "Dźwięk Bark",
"HTTP Headers": "Nagłówki HTTP",
"Trust Proxy": "Ufaj proxy",
"HomeAssistant": "Home Assistant",
"HomeAssistant": "Asystent domowy",
"RadiusSecret": "Sekretny klucz Radius",
"RadiusSecretDescription": "Współdzielony sekretny klucz pomiędzy klientem a serwerem",
"RadiusCalledStationId": "Id stacji wywoływanej",
@ -529,21 +529,21 @@
"promosmsLogin": "Nazwa logowania API",
"promosmsPassword": "Hasło API",
"pushoversounds pushover": "Pushover (domyślny)",
"pushoversounds bike": "Bike",
"pushoversounds bugle": "Bugle",
"pushoversounds cashregister": "Cash Register",
"pushoversounds bike": "Rower",
"pushoversounds bugle": "chrząszcz",
"pushoversounds cashregister": "Kasa fiskalna",
"pushoversounds classical": "Classical",
"pushoversounds cosmic": "Cosmic",
"pushoversounds falling": "Falling",
"pushoversounds cosmic": "Kosmiczny",
"pushoversounds falling": "Spadek",
"pushoversounds gamelan": "Gamelan",
"pushoversounds incoming": "Incoming",
"pushoversounds intermission": "Intermission",
"pushoversounds magic": "Magic",
"pushoversounds mechanical": "Mechanical",
"pushoversounds magic": "Magia",
"pushoversounds mechanical": "Mechaniczny",
"pushoversounds pianobar": "Piano Bar",
"pushoversounds siren": "Siren",
"pushoversounds spacealarm": "Space Alarm",
"pushoversounds tugboat": "Tug Boat",
"pushoversounds siren": "Syrena",
"pushoversounds spacealarm": "Alarm kosmiczny",
"pushoversounds tugboat": "Holownik",
"pushoversounds alien": "Alien Alarm (długie)",
"pushoversounds climb": "Climb (długie)",
"pushoversounds persistent": "Persistent (długie)",
@ -686,9 +686,15 @@
"Packet Size": "Rozmiar pakietu",
"uninstalling": "Odinstalowywanie",
"loadingError": "Nie można pobrać danych, proszę spróbować ponownie później.",
"plugin": "Wtyczka | Wtyczki",
"plugin": "Plugin | Pluginy",
"install": "Instaluj",
"installing": "Instalowanie",
"uninstall": "Odinstaluj",
"confirmUninstallPlugin": "Czy na pewno chcesz odinstalować tę wtyczkę?"
"confirmUninstallPlugin": "Czy na pewno chcesz odinstalować tę wtyczkę?",
"Custom Monitor Type": "Własny typ monitora",
"markdownSupported": "Obsługiwana składnia Markdown",
"Google Analytics ID": "Identyfikator Google Analytics",
"Edit Tag": "Edytuj Tag",
"Server Address": "Adres Serwera",
"Learn More": "Dowiedz się więcej"
}

@ -249,7 +249,7 @@
"enabled": "Ativado",
"setAsDefault": "Definir como padrão",
"Primary Base URL": "URL base principal",
"Resend Notification if Down X times consequently": "Reenviar notificação se OFFLINE X vezes consecutivamente",
"Resend Notification if Down X times consecutively": "Reenviar Notificação se OFFLINE X vezes consecutivamente",
"pushOptionalParams": "Parâmetros opcionais: {0}",
"webhookFormDataDesc": "{multipart} é bom para PHP. O JSON precisará ser analisado com {decodeFunction}",
"HeadersInvalidFormat": "Os cabeçalhos da solicitação não são um JSON válidos: ",
@ -269,5 +269,16 @@
"Start of maintenance": "Iniciar manutenção",
"All Status Pages": "Todas as Status Pages",
"Method": "Método",
"General Monitor Type": "Tipo de monitoramento geral"
"General Monitor Type": "Tipo de monitoramento geral",
"markdownSupported": "Sintaxe Markdown suportada",
"emojiCheatSheet": "Folha de dicas de emojis: {0}",
"topic": "Tema",
"topicExplanation": "Tópico MQTT para monitorar",
"successMessageExplanation": "Mensagem MQTT que será considerada como sucesso",
"Content Type": "Tipo de Conteúdo",
"Shrink Database": "Encolher Banco de Dados",
"Content": "Conteúdo",
"Pick a RR-Type...": "Escolha um tipo RR…",
"Pick Accepted Status Codes...": "Escolha Códigos de Status Aceitos…",
"Pick Affected Monitors...": "Escolher Monitores Afetados…"
}

@ -1,7 +1,7 @@
{
"languageName": "Português (Portugal)",
"checkEverySecond": "Verificar a cada {0} segundos.",
"retryCheckEverySecond": "Tentar novamente a cada {0} segundos.",
"checkEverySecond": "Verificar a cada {0} segundos",
"retryCheckEverySecond": "Tentar novamente a cada {0} segundos",
"retriesDescription": "Máximo de tentativas antes que o serviço seja marcado como inativo e uma notificação seja enviada",
"ignoreTLSError": "Ignorar erros TLS/SSL para sites HTTPS",
"upsideDownModeDescription": "Inverte o status de cabeça para baixo. Se o serviço estiver acessível, ele está OFFLINE.",
@ -72,7 +72,7 @@
"Heartbeat Retry Interval": "Intervalo de repetição de Heartbeats",
"Advanced": "Avançado",
"Upside Down Mode": "Modo de cabeça para baixo",
"Max. Redirects": "Redirecionamento Máx.",
"Max. Redirects": "Max. Redirecionamentos",
"Accepted Status Codes": "Status Code Aceitáveis",
"Save": "Guardar",
"Notifications": "Notificações",
@ -131,7 +131,7 @@
"Create": "Criar",
"Clear Data": "Limpar Dados",
"Events": "Eventos",
"Heartbeats": "Heartbeats",
"Heartbeats": "Pings",
"Auto Get": "Obter Automático",
"backupDescription": "Podes fazer backup de todos os monitores e todas as notificações num arquivo JSON.",
"backupDescription2": "OBS: Os dados do histórico e do evento não estão incluídos.",
@ -147,14 +147,14 @@
"Setup 2FA": "Configurar 2FA",
"Enable 2FA": "Ativar 2FA",
"Disable 2FA": "Desativar 2FA",
"2FA Settings": "Configurações do 2FA ",
"2FA Settings": "Configurações do 2FA",
"Two Factor Authentication": "Autenticação de Dois Fatores",
"Active": "Ativo",
"Inactive": "Inativo",
"Token": "Token",
"Show URI": "Mostrar URI",
"Tags": "Tag",
"Add New below or Select...": "Adicionar Novo abaixo ou Selecionar ...",
"Add New below or Select...": "Adicionar Novo abaixo ou Selecionar",
"Tag with this name already exist.": "Já existe uma etiqueta com este nome.",
"Tag with this value already exist.": "Já existe uma etiqueta com este valor.",
"color": "cor",
@ -167,9 +167,9 @@
"Indigo": "Índigo",
"Purple": "Roxo",
"Pink": "Rosa",
"Search...": "Pesquisa...",
"Avg. Ping": "Ping Médio.",
"Avg. Response": "Resposta Média. ",
"Search...": "Pesquisa",
"Avg. Ping": "Ping Médio",
"Avg. Response": "Resposta Média",
"Status Page": "Página de Status",
"Status Pages": "Página de Status",
"Entry Page": "Página de entrada",
@ -181,5 +181,263 @@
"Add Group": "Adicionar Grupo",
"Add a monitor": "Adicionar um monitor",
"Edit Status Page": "Editar Página de Status",
"Go to Dashboard": "Ir para o dashboard"
"Go to Dashboard": "Ir para o dashboard",
"backupOutdatedWarning": "Depreciado: Uma vez que muitas funcionalidades foram adicionadas e esta funcionalidade de backup é um pouco desmanchada, não pode gerar ou restaurar um backup completo.",
"Schedule maintenance": "Agendar manutenção",
"Affected Monitors": "Monitores Afetados",
"Pick Affected Monitors...": "Escolher Monitores Afetados…",
"All Status Pages": "Todas as Páginas de Status",
"Select status pages...": "Selecionar Páginas de Status…",
"defaultNotificationName": "Meu alerta de {notification} ({number})",
"here": "aqui",
"Required": "Obrigatório",
"Post URL": "Post URL",
"Content Type": "Tipo de Conteúdo",
"webhookFormDataDesc": "{multipart} é bom para PHP. O JSON precisará ser analisado com {decodeFunction}",
"webhookAdditionalHeadersTitle": "Headers Adicionais",
"Webhook URL": "URL do Webhook",
"Application Token": "Token do Aplicativo",
"Server URL": "URL do Servidor",
"Priority": "Prioridade",
"emojiCheatSheet": "Folha de dicas de emojis: {0}",
"Read more": "Ler Mais",
"Method": "Método",
"Body": "Body",
"Headers": "Headers",
"PushUrl": "Enviar URL",
"HeadersInvalidFormat": "Os headers da solicitação não são JSON válidos: ",
"BodyInvalidFormat": "O body da solicitação não é um JSON válido: ",
"Monitor History": "Histórico do Monitor",
"clearDataOlderThan": "Mantenha os dados do histórico do monitor por {0} dias.",
"PasswordsDoNotMatch": "As passwords não coincidem.",
"records": "registros",
"One record": "Um registro",
"steamApiKeyDescription": "Para monitorar um Steam Game Server, você precisa de uma chave Steam Web-API. Pode registrar a chave da API aqui: ",
"Current User": "Usuário Atual",
"topicExplanation": "Tópico MQTT para monitorar",
"successMessage": "Mensagem de Sucesso",
"recent": "Recente",
"Done": "Feito",
"Info": "Informações",
"Security": "Segurança",
"Steam API Key": "Steam API Key",
"Shrink Database": "Encolher Base de Dados",
"Pick a RR-Type...": "Escolha um tipo RR…",
"Pick Accepted Status Codes...": "Escolha Códigos de Status Aceitos…",
"HTTP Options": "Opções HTTP",
"Create Incident": "Criar Incidente",
"Content": "Conteúdo",
"Style": "Estilo",
"info": "informações",
"warning": "aviso",
"danger": "perigo",
"critical": "crítico",
"primary": "primário",
"light": "luz",
"dark": "escuro",
"Post": "Post",
"Created": "Criado",
"Last Updated": "Ultima Atualização",
"Unpin": "Desmarcar",
"Switch to Light Theme": "Alterar para Tema Claro",
"Switch to Dark Theme": "Alterar para Tema Escuro",
"Show Tags": "Mostrar Tags",
"appriseInstalled": "Apprise está instalado.",
"appriseNotInstalled": "Apprise não está instalado. {0}",
"No monitors available.": "Nenhum monitor disponível.",
"Add one": "Adicione um",
"No Monitors": "Sem Monitores",
"Untitled Group": "Grupo sem Título",
"Services": "Serviços",
"Discard": "Descartar",
"Cancel": "Cancelar",
"Powered by": "Powered by",
"Customize": "Customizar",
"Custom CSS": "CSS Customizado",
"Custom Footer": "Footer Customizado",
"deleteStatusPageMsg": "Tem certeza de que deseja excluir esta página de status?",
"Proxies": "Proxies",
"default": "Padrão",
"enabled": "Ativar",
"setAsDefault": "Definir como Padrão",
"deleteProxyMsg": "Tem a certeza que quer excluir este proxy para todos os monitores?",
"setAsDefaultProxyDescription": "Este proxy será ativado por padrão para novos monitores. Você ainda pode desabilitar o proxy separadamente para cada monitor.",
"Valid": "Válido",
"Invalid": "Inválido",
"Remove Token": "Remover Token",
"Running": "Em Execução",
"Not running": "Não está em execução",
"Start": "Iniciar",
"Stop": "Parar",
"Add New Status Page": "Adicionar Nova Página de Status",
"Next": "Próximo",
"No consecutive dashes": "Sem traços consecutivos",
"Slug": "URL",
"Accept characters:": "Caracteres aceites:",
"startOrEndWithOnly": "Iniciar ou terminar apenas com {0}",
"The slug is already taken. Please choose another slug.": "URL já existe. Por favor escolha outro URL.",
"No Proxy": "Sem Proxy",
"Authentication": "Autenticação",
"HTTP Basic Auth": "Autenticação Básica HTTP",
"New Status Page": "Nova Página de Status",
"Page Not Found": "Página Não Encontrada",
"Reverse Proxy": "Proxy Reverso",
"Backup": "Backup",
"About": "Sobre",
"wayToGetCloudflaredURL": "(Download cloudflared de {0})",
"cloudflareWebsite": "Site da Cloudflare",
"Message:": "Mensagem:",
"HTTP Headers": "Headers HTTP",
"Trust Proxy": "Proxy de Confiança",
"Other Software": "Outro Software",
"For example: nginx, Apache and Traefik.": "Por exemplo: nginx, Apache e Traefik.",
"Please read": "Por favor leia",
"Subject:": "Assunto:",
"Valid To:": "Valido para:",
"Days Remaining:": "Dias Restantes:",
"Issuer:": "Emissor:",
"Fingerprint:": "Impressão Digital:",
"No status pages": "Nenhuma página de status",
"Domain Name Expiry Notification": "Notificação de Expiração de Nome de Domínio",
"Proxy": "Proxy",
"Date Created": "Data da Criação",
"Footer Text": "Texto do Footer",
"Show Powered By": "Mostrar Powered By",
"Domain Names": "Nomes de Domínio",
"signedInDisp": "Conectado como {0}",
"signedInDispDisabled": "Autenticação Desativada.",
"RadiusSecret": "Radius Secret",
"RadiusSecretDescription": "Secret compartilhado entre cliente e servidor",
"RadiusCallingStationIdDescription": "Identificador do dispositivo de chamada",
"Certificate Expiry Notification": "Notificação de Expiração do Certificado",
"API Username": "Nome de utilizador da API",
"API Key": "Chave API",
"Using a Reverse Proxy?": "Utilizando um Proxy Reverso?",
"Check how to config it for WebSocket": "Verifique como configurá-lo para WebSocket",
"Steam Game Server": "Steam Game Server",
"Most likely causes:": "Causas mais prováveis:",
"The resource is no longer available.": "O recurso já não está disponível.",
"There might be a typing error in the address.": "Pode haver um erro de digitação no endereço.",
"What you can try:": "O que pode tentar:",
"Retype the address.": "Volte a escrever o endereço.",
"Go back to the previous page.": "Voltar à página anterior.",
"Coming Soon": "Em Breve",
"Connection String": "Linha de Conexão",
"Query": "Query",
"settingsCertificateExpiry": "Validade do Certificado TLS",
"certificationExpiryDescription": "Os monitores HTTPS ativam a notificação quando o certificado TLS expira:",
"Setup Docker Host": "Configuração do Docker Host",
"Connection Type": "Tipo de conexão",
"Docker Daemon": "Docker Daemon",
"deleteDockerHostMsg": "Tem a certeza de querer apagar este docker host para todos os monitores?",
"socket": "Socket",
"tcp": "TCP / HTTP",
"Docker Host": "Docker Host",
"Docker Hosts": "Docker Hosts",
"Domain": "Domínio",
"Workstation": "Estação de trabalho",
"Packet Size": "Tamanho do pacote",
"ZohoCliq": "ZohoCliq",
"Bot Token": "Token do Bot",
"wayToGetTelegramToken": "Pode obter o token a partir de {0}.",
"Chat ID": "ID do Chat",
"wayToGetTelegramChatID": "Pode obter o seu ID de chat enviando uma mensagem para o bot e indo a este URL para ver o chat_id:",
"YOUR BOT TOKEN HERE": "O TOKEN DO BOT AQUI",
"disableCloudflaredNoAuthMsg": "Está no modo Sem Autenticação, não é necessária uma palavra-passe.",
"Examples": "Exemplos",
"Long-Lived Access Token": "Token de Acesso de Longa Duração",
"wayToGetLineNotifyToken": "Pode obter o código de acesso a partir de {0}",
"Notification Service": "Serviço de Notificação",
"A list of Notification Services can be found in Home Assistant under \"Developer Tools > Services\" search for \"notification\" to find your device/phone name.": "Uma lista de Serviços de Notificação pode ser encontrada em Home Assistant em \"Developer Tools > Services\" pesquisa por \"notificação\" para encontrar o seu dispositivo/nome do telefone.",
"Home Assistant URL": "URL do Home Assistant",
"Event type:": "Tipo de evento:",
"Event data:": "Dados do evento:",
"Then choose an action, for example switch the scene to where an RGB light is red.": "Depois de escolher uma ação, por exemplo mudar a cena para onde uma luz RGB é vermelha.",
"Frontend Version": "Versão Frontend",
"Frontend Version do not match backend version!": "Versão Frontend não corresponde à versão backend!",
"backupRecommend": "Por favor, faça o backup do volume ou da pasta de dados (./data/) diretamente.",
"Optional": "Opcional",
"squadcast": "Squadcast",
"recurringInterval": "Intervalo",
"Recurring": "Recurrente",
"strategyManual": "Ativar/Desativar Manualmente",
"warningTimezone": "Está a utilizar o fuso horário do servidor",
"weekdayShortMon": "Segunda",
"weekdayShortTue": "Terça",
"weekdayShortWed": "Quarta",
"weekdayShortThu": "Quinta",
"weekdayShortFri": "Sexta",
"weekdayShortSat": "Sábado",
"weekdayShortSun": "Domingo",
"dayOfWeek": "Dia da Semana",
"dayOfMonth": "Dia do Mês",
"lastDay": "Último Dia",
"lastDay2": "2º Último Dia do Mês",
"lastDay3": "3º Último Dia do Mês",
"lastDay4": "4º Último Dia do Mês",
"No Maintenance": "Nenhuma Manutenção",
"maintenanceStatus-under-maintenance": "Em Manutenção",
"maintenanceStatus-inactive": "Inativo",
"maintenanceStatus-scheduled": "Agendado",
"maintenanceStatus-ended": "Terminado",
"Display Timezone": "Mostrar Fuso horário",
"Server Timezone": "Fuso horário do Servidor",
"statusPageMaintenanceEndDate": "Acabou",
"Maintenance": "Manutenção",
"Specific Monitor Type": "Tipo de Monitor Específico",
"Resend Notification if Down X times consequently": "Reenviar notificação se Off X vezes consequentemente",
"resendEveryXTimes": "Reenviar a cada {0} vezes",
"resendDisabled": "Reenviar desativado",
"Push URL": "Enviar URL",
"webhook": "Webhook",
"topic": "Tema",
"RadiusCalledStationIdDescription": "Identificador do dispositivo chamado",
"Automations can optionally be triggered in Home Assistant:": "As automatizações podem opcionalmente ser ativadas em Home Assistant:",
"or": "ou",
"markdownSupported": "Sintaxe de redução suportada",
"Start of maintenance": "Início da manutenção",
"webhookJsonDesc": "{0} é bom para qualquer servidor HTTP moderno, como Express.js",
"webhookAdditionalHeadersDesc": "Define headers adicionais enviados com o webhook.",
"successMessageExplanation": "Mensagem MQTT que será considerada como sucesso",
"error": "erro",
"Please input title and content": "Por favor insira o título e o conteúdo",
"Hide Tags": "Ocultar Tags",
"Description": "Descrição",
"shrinkDatabaseDescription": "Acionar banco de dados VACUUM para SQLite. Se seu banco de dados for criado após 1.10.0, AUTO_VACUUM já está ativado e esta ação não é necessária.",
"proxyDescription": "Os proxies devem ser atribuídos a um monitor para funcionar.",
"enableProxyDescription": "Este proxy não afetará as solicitações do monitor até que seja ativado. Você pode controlar temporariamente a desativação do proxy de todos os monitores pelo status de ativação.",
"Don't know how to get the token? Please read the guide:": "Não sabe como obter o token? Por favor, leia o guia:",
"The current connection may be lost if you are currently connecting via Cloudflare Tunnel. Are you sure want to stop it? Type your current password to confirm it.": "A conexão atual pode ser perdida se estiver conectando via Cloudflare Tunnel. Tem certeza de que deseja pará-lo? Digite sua senha atual para confirmar.",
"Docker Container": "Contentor Docker",
"Container Name / ID": "Nome / ID do Contentor",
"supportTelegramChatID": "Chat de Apoio Direto / Grupo / ID do Chat do Canal",
"chatIDNotFound": "O ID do Chat não é encontrado; por favor envie uma mensagem a este bot primeiro",
"trustProxyDescription": "Confiar nos headers 'X-Forwarded-*'. Se quiser obter o IP correto do cliente e o seu Uptime Kuma está por detrás de um proxy como o Nginx ou Apache, deve activá-lo.",
"Long-Lived Access Token can be created by clicking on your profile name (bottom left) and scrolling to the bottom then click Create Token. ": "O Token de Acesso de Longa Duração pode ser criado clicando no nome do seu perfil (em baixo à esquerda) e descendo para o fundo da pagina e depois clicando em Criar Token. ",
"lastDay1": "Último Dia do Mês",
"pauseMaintenanceMsg": "Quer mesmo colocar em pausa?",
"maintenanceStatus-unknown": "Desconhecido",
"needPushEvery": "Deve chamar este URL a cada {0} segundos.",
"pushOptionalParams": "Parâmetros opcionais: {0}",
"Title": "Título",
"User": "Utilizador",
"Installed": "Instalado",
"Not installed": "Não instalado",
"RadiusCalledStationId": "Id da estação chamada",
"RadiusCallingStationId": "Id da estação de chamada",
"default: notify all devices": "padrão: notificar todos os dispositivos",
"Trigger type:": "Tipo de gatilho:",
"telegram": "Telegram",
"Help": "Ajuda",
"Game": "Jogo",
"Monitor": "Monitor | Monitores",
"Default": "Padrão",
"Certificate Chain": "Certificate Chain",
"Show update if available": "Mostrar atualização se disponível",
"Also check beta release": "Verifique também a versão beta",
"Primary Base URL": "URL Base Principal",
"statusMaintenance": "Manutenção",
"Passive Monitor Type": "Tipo de Monitor Passivo",
"Custom": "Personalizar",
"General Monitor Type": "Tipo de Monitor Geral"
}

@ -1,3 +1,563 @@
{
"languageName": "Limba română"
"languageName": "Română",
"Dashboard": "Panou de Control",
"Help": "Ajutor",
"Appearance": "Aspect",
"Theme": "Temă",
"General": "General",
"Version": "Versiune",
"Check Update On GitHub": "Verifică Actualitatea pe GitHub",
"Quick Stats": "Statistici Rapide",
"Up": "Sus",
"Down": "Jos",
"statusMaintenance": "Mentenanță",
"Maintenance": "Mentenanță",
"General Monitor Type": "Monitor de Tip General",
"Passive Monitor Type": "Monitor de Tip Pasiv",
"markdownSupported": "Limbaj Markdown Acceptat",
"Pause": "Pauză",
"Name": "Nume",
"Status": "Status",
"DateTime": "DatăOră",
"Message": "Mesaj",
"No important events": "Niciun eveniment important",
"Resume": "Reia",
"Delete": "Șterge",
"Uptime": "Timpul de funcționare",
"Cert Exp.": "Expirarea Certificatului",
"Monitor": "Monitor | Monitoare",
"day": "zi | zile",
"-day": "-zi",
"hour": "oră",
"Edit": "Modifică",
"Ping": "Ping",
"Monitor Type": "Tipul Monitorului",
"Keyword": "Cuvânt Cheie",
"Friendly Name": "Nume Ușor de Recunoscut",
"URL": "URL",
"Hostname": "Hostname",
"Port": "Port",
"Retries": "Reîncercări",
"Heartbeat Retry Interval": "Intervalul Reîncercării Heartbeat-ului",
"Advanced": "Avansat",
"checkEverySecond": "Verifică la fiecare {0} secunde",
"retryCheckEverySecond": "Reîncearcă la fiecare {0} secunde",
"resendEveryXTimes": "Retrimite de {0} ori",
"resendDisabled": "Retrimiterea dezactivată",
"ignoreTLSError": "Ignoră erorile TLS/SSL pentru site-urile HTTPS",
"upsideDownModeDescription": "Întoarce statusul cu susul în jos. Dacă serviciul este contactabil, este OFFLINE.",
"Upside Down Mode": "Modul cu Susul in Jos",
"Max. Redirects": "Nr. Max. de Redirecționări",
"Accepted Status Codes": "Coduri de Status Acceptate",
"Push URL": "Împinge URL",
"needPushEvery": "Acest URL trebuie să fie contactat la fiecare {0} secunde.",
"pushOptionalParams": "Parametrii opționali: {0}",
"Save": "Salvează",
"Notifications": "Notificări",
"Not available, please setup.": "Indisponibil, trebuie configurat.",
"Setup Notification": "Configurare Notificări",
"Light": "Luminos",
"Dark": "Întunecat",
"Auto": "Automat",
"Normal": "Normal",
"Bottom": "Fund",
"None": "Nimic",
"Timezone": "Fus Orar",
"Search Engine Visibility": "Vizibilitate în Motoarele de Căutare",
"Allow indexing": "Permite Indexarea",
"Change Password": "Schimbă Parola",
"Current Password": "Parola Curentă",
"New Password": "Parolă Nouă",
"Repeat New Password": "Repetă Parola Nouă",
"Update Password": "Actualizează Parola",
"Disable Auth": "Dezactivează Autentificarea",
"Enable Auth": "Activează Autentificarea",
"disableauth.message1": "Ești sigur că vrei să <strong>dezactivezi autentificarea</strong>?",
"Please use this option carefully!": "Utilizează Această Opțiune cu Grijă!",
"Logout": "Delogare",
"Leave": "Părăsește",
"I understand, please disable": "Am luat la cunoștință, dezactivează",
"Confirm": "Confirmă",
"Yes": "Da",
"No": "Nu",
"Username": "Nume de Utilizator",
"Password": "Parolă",
"Remember me": "Ține-mă Minte",
"No Monitors, please": "Niciun monitor, te rog",
"add one": "adaugă unul",
"Resource Record Type": "Tipul de Înregistrare a Resurselor",
"Create your admin account": "Crează un Cont de Administrator",
"Repeat Password": "Repetă Parola",
"Import Backup": "Importează Backup-ul",
"Export Backup": "Exporta Backup-ul",
"Export": "Exportează",
"Import": "Importă",
"respTime": "Timp de Răspuns (ms)",
"Apply on all existing monitors": "Aplică pentru toate monitoarele existente",
"Clear Data": "Șterge Datele",
"Events": "Evenimente",
"Heartbeats": "Heartbeat-uri",
"Auto Get": "Obține Automat",
"Affected Monitors": "Monitoare Afectate",
"Pick Affected Monitors...": "Alege Monitoarele Afectate…",
"Start of maintenance": "Începerea Mentenanței",
"All Status Pages": "Toate Paginile de Status",
"Skip existing": "Sari Existente",
"Overwrite": "Suprascrie",
"Options": "Opțiuni",
"Keep both": "Păstrează Ambele",
"Verify Token": "Verifică Token-ul",
"Enable 2FA": "Activează Autentificarea în Doi Pași",
"Disable 2FA": "Dezactivează Autentificarea în Doi Pași",
"2FA Settings": "Setări Autentificare în Doi Pași",
"Active": "Activ",
"Token": "Token",
"Show URI": "Arată URI",
"Tags": "Etichete",
"Tag with this name already exist.": "Deja Există o Etichetă cu Acest Nume.",
"Tag with this value already exist.": "Deja Există o Etichetă cu Această Valoare.",
"color": "Culoare",
"value (optional)": "valoare (opțional)",
"Gray": "Gri",
"Red": "Roșu",
"Orange": "Portocaliu",
"Green": "Verde",
"Blue": "Albastru",
"Indigo": "Indigo",
"Purple": "Violet",
"Custom": "Personalizat",
"Entry Page": "Pagina de Implicită",
"No Services": "Niciun Serviciu",
"All Systems Operational": "Toate Sistemele Operaționale",
"Partially Degraded Service": "Servicii Parțial Degradate",
"Degraded Service": "Servicii Degradate",
"Add Group": "Adaugă Grup",
"Add a monitor": "Adaugă Monitor",
"Edit Status Page": "Modifică Pagina de Status",
"Status Page": "Pagina de Status",
"Status Pages": "Pagini de Status",
"defaultNotificationName": "A mea {notification} Alertă ({number})",
"here": "aici",
"Required": "Necesar",
"webhook": "Webhook",
"Post URL": "Postează URL",
"Content Type": "Tipul Conținutului",
"webhookFormDataDesc": "{multipart} este bun pentru PHP. JSON-ul va fi analizat cu {decodeFunction}",
"webhookAdditionalHeadersTitle": "Antete adiționale",
"Webhook URL": "URL-ul Webhook-ului",
"Application Token": "Token-ul Aplicației",
"Server URL": "URL-ul Server-ului",
"Priority": "Prioritate",
"emojiCheatSheet": "Emoji-uri: {0}",
"Read more": "Vezi Mai Mult",
"appriseInstalled": "Apprise instalat.",
"appriseNotInstalled": "Apprise Neinstalat. {0}",
"Method": "Metodă",
"Body": "Corp",
"Headers": "Antete",
"PushUrl": "Împinge URL",
"BodyInvalidFormat": "Formatul corpului de request nu este valid: ",
"Monitor History": "Istoricul Monitorului",
"PasswordsDoNotMatch": "Parolele nu sunt la fel.",
"One record": "O înregistrare",
"Current User": "Utilizatorul Curent",
"topic": "Subiect",
"topicExplanation": "Subiectul MQTT către monitor",
"successMessage": "Mesaj de Succes",
"successMessageExplanation": "Mesajul MQTT care va fi considerat un succes",
"Done": "Terminat",
"Info": "Informații",
"Security": "Securitate",
"Shrink Database": "Miceste Baza de Date",
"Default": "Implicit",
"HTTP Options": "Opțiuni HTTP",
"Title": "Titlu",
"Content": "Conținut",
"Style": "Stil",
"info": "informații",
"warning": "avertizare",
"danger": "pericol",
"error": "eroare",
"critical": "critic",
"dark": "întunecat",
"Post": "Postează",
"Last Updated": "Actualizat",
"Unpin": "Desprinde",
"Switch to Light Theme": "Schimbă la Tema Luminoasă",
"Show Tags": "Arată Etichetele",
"Hide Tags": "Ascunde Etichetele",
"Description": "Descriere",
"No monitors available.": "Niciun monitor disponibil.",
"Discard": "Elimină",
"Cancel": "Anulează",
"Powered by": "Cu ajutorul",
"Customize": "Personalizează",
"Custom Footer": "Subsol Personalizat",
"Custom CSS": "CSS Personalizat",
"deleteStatusPageMsg": "Ești sigur că vrei să ștergi această pagină de status?",
"Proxies": "Proxy-uri",
"default": "Implicit",
"enabled": "Activat",
"setAsDefault": "Setează ca Implicit",
"deleteProxyMsg": "Ești sigur că vrei să ștergi acest proxy pentru toate monitoarele?",
"Certificate Chain": "Lanț-ul Certificatului",
"Valid": "Valid",
"Invalid": "Invalid",
"User": "Utilizator",
"Installed": "Instalat",
"Running": "Operează",
"Not running": "Nu operează",
"Remove Token": "Elimină token-ul",
"Start": "Start",
"Stop": "Stop",
"Add New Status Page": "Adaugă o Pagină de Status Nouă",
"Slug": "Slug",
"startOrEndWithOnly": "Începe sau termină doar cu {0}",
"No consecutive dashes": "Fără cratime consecutive",
"Next": "Înainte",
"No Proxy": "Niciun Proxy",
"Authentication": "Autentificate",
"HTTP Basic Auth": "HTTP Basic Auth",
"New Status Page": "Pagină de Status Nouă",
"Page Not Found": "Pagină Negăsită",
"Backup": "Backup",
"About": "Despre",
"wayToGetCloudflaredURL": "(Cloudflared a fost descărcat de la {0})",
"cloudflareWebsite": "Website-ul Cloudflare",
"Message:": "Mesaj:",
"HTTP Headers": "Antete HTTP",
"Trust Proxy": "Ai încredere în Proxy",
"Other Software": "Alt Software",
"For example: nginx, Apache and Traefik.": "De exemplu: nginx, Apache și Traefik.",
"Please read": "Te rog citește",
"Subject:": "Subiect:",
"Valid To:": "Valid Pâna la:",
"Days Remaining:": "Zile rămase:",
"Issuer:": "Emitent:",
"Fingerprint:": "Amprentă:",
"No status pages": "Nicio pagină de status",
"Domain Name Expiry Notification": "Notificare cu Privire la Expirarea Numelui de Domeniu",
"Proxy": "Proxy",
"Date Created": "Data Creării",
"Footer Text": "Text-ul pentru subsol",
"Show Powered By": "Arată ”Cu ajutorul”",
"Reverse Proxy": "Proxy invers",
"Domain Names": "Nume de domeniu",
"signedInDisp": "Autentificat ca {0}",
"signedInDispDisabled": "Autentificare Dezactivată.",
"RadiusSecret": "Secret Radius",
"RadiusSecretDescription": "Secret împărtășit cu client-ul și server-ul",
"RadiusCalledStationId": "ID-ul Stației Contactate",
"RadiusCalledStationIdDescription": "Identificatorul serviciului apelat",
"RadiusCallingStationId": "ID-ul Stației Contactante",
"RadiusCallingStationIdDescription": "Identificatorul dispozitivului contactant",
"API Username": "Nume de utilizator al API-ului",
"API Key": "Cheie API",
"Also check beta release": "Verifică și actualizările beta",
"Using a Reverse Proxy?": "Folosești un Proxy Invers?",
"Check how to config it for WebSocket": "Află cum să îl configurezi pentru WebSocket",
"Steam Game Server": "Server de Joc Steam",
"Most likely causes:": "Cea mai probabilă cauză:",
"There might be a typing error in the address.": "Ar putea exista o eroare de scriere în adresă.",
"What you can try:": "Ce poți încerca:",
"Retype the address.": "Rescrie adresa.",
"Go back to the previous page.": "Mergi la pagina precedentă.",
"Coming Soon": "În curând.",
"Connection String": "Connection String",
"Query": "Query",
"settingsCertificateExpiry": "Expirarea certificatului TLS",
"Setup Docker Host": "Configurează Docker Host",
"Connection Type": "Tipul Conexiunii",
"Docker Daemon": "Docker Daemon",
"deleteDockerHostMsg": "Ești sigur că vrei să ștergi acest docker host pentru toate montoarele?",
"socket": "Socket",
"tcp": "TCP / HTTP",
"Docker Container": "Container Docker",
"Container Name / ID": "Numele Container-ului / ID",
"Docker Host": "Docker Host",
"Domain": "Domeniu",
"Workstation": "Stație de lucru",
"Packet Size": "Mărime Pachet",
"telegram": "Telegram",
"ZohoCliq": "ZohoCliq",
"Bot Token": "Token Robot",
"wayToGetTelegramToken": "Poți obține un token de la {0}.",
"Chat ID": "ID-ul Chat-ului",
"YOUR BOT TOKEN HERE": "TOKEN-UL TĂU DE ROBOT",
"chatIDNotFound": "ID-ul Chat-ului nu a fost găsit; te rog întâi trimite un mesaj către robot",
"disableCloudflaredNoAuthMsg": "Ești în modul fără autentificare, nu ai nevoie de o parola.",
"wayToGetLineNotifyToken": "Poți obține un token de acces de la {0}",
"Examples": "Exemple",
"Home Assistant URL": "URL-ul de la Home Assistant",
"Long-Lived Access Token": "Token de acces cu durata de viață mare",
"default: notify all devices": "implicit: notifică toate dispozitivele",
"Automations can optionally be triggered in Home Assistant:": "Automatizările pot fi declanșate opțional în Home Assistant:",
"Trigger type:": "Tipul Declanșatorului:",
"Event type:": "Tipul Evenimentului:",
"Event data:": "Datele Evenimentului:",
"Then choose an action, for example switch the scene to where an RGB light is red.": "Apoi alege o acțiune, de exemplu, schimbă un LED RGB în roșu.",
"Frontend Version": "Versiunea Frontend-ului",
"Frontend Version do not match backend version!": "Versiunea Frontend-ului nu este aceeași cu cea a backend-ului!",
"backupRecommend": "Te rog fă o copie a directorului (./data/) în loc.",
"Optional": "Opțional",
"squadcast": "Squadcast",
"or": "sau",
"recurringInterval": "Interval",
"Recurring": "Recurentă",
"strategyManual": "Activ/Inactiv Manual",
"warningTimezone": "Folosește fusul orar al server-ului",
"weekdayShortMon": "Luni",
"weekdayShortTue": "Marți",
"weekdayShortWed": "Miercuri",
"weekdayShortThu": "Joi",
"weekdayShortFri": "Vineri",
"weekdayShortSat": "Sâmbătă",
"weekdayShortSun": "Duminică",
"dayOfWeek": "Ziua săptămânii",
"dayOfMonth": "Ziua lunii",
"lastDay": "Ultima zi",
"lastDay1": "Ultima zi a Lunii",
"lastDay2": "Penultima zi a Lunii",
"lastDay3": "Antepenultima zi a Lunii",
"No Maintenance": "Fără mentenanță",
"pauseMaintenanceMsg": "Ești sigur că vrei sa pui pe pauză?",
"maintenanceStatus-under-maintenance": "În mentenanță",
"maintenanceStatus-inactive": "Inactiv",
"maintenanceStatus-scheduled": "Planificat",
"maintenanceStatus-ended": "Terminat",
"maintenanceStatus-unknown": "Necunoscut",
"Server Timezone": "Fusul Orar al Server-ului",
"statusPageMaintenanceEndDate": "Sfârșit",
"IconUrl": "URL-ul pictogramei",
"Enable DNS Cache": "Activează DNS Cache",
"Enable": "Activează",
"Disable": "Dezactivează",
"Effective Date Range": "Interval în care se aplică",
"Schedule Maintenance": "Planifică Mentenanță",
"Date and Time": "Dată și Oră",
"DateTime Range": "Interval DatăOră",
"loadingError": "Nu se pot obține datele, te rog încearcă mai târziu.",
"plugin": "Plugin | Plugin-uri",
"install": "Instalează",
"installing": "Instalare",
"uninstall": "Dezinstalează",
"confirmUninstallPlugin": "Ești sigur că vrei să dezinstalezi acest plugin?",
"smtp": "Email (SMTP)",
"secureOptionNone": "Niciunul / STARTTLS (25, 587)",
"secureOptionTLS": "TLS (456)",
"From Email": "De la Email",
"emailCustomSubject": "Subiect Personalizat",
"To Email": "La Email",
"smtpCC": "CC",
"smtpBCC": "BCC",
"Discord Webhook URL": "URL-ul Webhook-ului Discord",
"Bot Display Name": "Numele Robotului",
"Prefix Custom Message": "Prefix Personalizat",
"Hello @everyone is...": "Salut {'@'}everyone sunt…",
"wayToGetTeamsURL": "Poți învăța cum să creezi un URL webhook {0}.",
"wayToGetZohoCliqURL": "Poți învăța cum să creezi un URL webhook {0}.",
"needSignalAPI": "Trebuie să ai un client signal cu API-ul REST.",
"Number": "Număr",
"Recipients": "Destinatari",
"Access Token": "Token de acces",
"Channel access token": "Token de acces al canalului",
"Line Developers Console": "Consola Dezvoltatorilor Line",
"lineDevConsoleTo": "Consola Dezvoltatorilor Line - {0}",
"Basic Settings": "Setări de Bază",
"User ID": "ID-ul Utilizatorului",
"Messaging API": "API-ul pentru Mesagerie",
"Icon URL": "URL-ul Pictogramei",
"dataRetentionTimeError": "Perioada de renenție trebuie să fie 0 sau mai mare",
"infiniteRetention": "Setează la „0” pentru retenție pe perioadă nedeterminată.",
"confirmDeleteTagMsg": "Ești sigur că vrei să ștergi această etichetă? Monitoarele asociate cu această etichetă nu vor fi șterse.",
"enableGRPCTls": "Permite trimiterea cererilor gRPC cu conexiune TLS",
"grpcMethodDescription": "Numele metodei este convert to cammelCase format cum ar fi sayHello, check, etc.",
"deleteMonitorMsg": "Ești sigur că vrei să ștergi acest monitor?",
"deleteMaintenanceMsg": "Ești sigur că vrei să ștergi această mentenanță?",
"dnsPortDescription": "Port-ul server-ului DNS. Este implicit 53. Poți schimba acest port oricând.",
"resolverserverDescription": "Cloudflare este server-ul implicit. Poți schimba asta oricând.",
"rrtypeDescription": "Selectează tipul RR pe care vrei să îl monitorizezi",
"pauseMonitorMsg": "Ești sigur că vrei să pui pe pauză?",
"clearEventsMsg": "Ești sigur că vrei să ștergi toate evenimentele asociate cu acest monitor?",
"clearHeartbeatsMsg": "Ești sigur că vrei să ștergi toate heartbeat-urile asociate cu acest monitor?",
"confirmClearStatisticsMsg": "Ești sigur că vrei să ștergi TOATE statisticile?",
"confirmImportMsg": "Ești sigur că vrei să importezi backup-ul? Te rog verifică dacă ai selectat varianta corectă de importare.",
"twoFAVerifyLabel": "Te rog introdu token-ul pentru a verifica Autentificarea în Doi Pași:",
"tokenValidSettingsMsg": "Token-ul este valid! Acum poți salva setările legate de Autentificarea în Doi Pași.",
"confirmEnableTwoFAMsg": "Ești sigur că vrei să activezi Autentificarea în Doi Pași?",
"recurringIntervalMessage": "Rulează o dată pe zi | Rulează o dată la {0} zile",
"affectedMonitorsDescription": "Selectează monitoarele afectate de această mentenanță",
"atLeastOneMonitor": "Selectează cel puțin un monitor afectat",
"passwordNotMatchMsg": "Parolele nu se potrivesc.",
"notificationDescription": "Notificările trebuie atribuite unui monitor pentru a funcționa.",
"backupDescription": "Acum poți face backup la toate monitoarele și notificările într-un fișier JSON.",
"backupDescription2": "Notă: istoricul și datele evenimentelor nu sunt incluse.",
"endpoint": "Punct final",
"octopushAPIKey": "„Cheia API” din credențialele HTTP API în panoul de control",
"octopushLogin": "„Logare” din credențialele HTTP API în panoul de control",
"promosmsLogin": "Numele de Login API",
"promosmsPassword": "Parola API",
"pushoversounds pushover": "Pushover (implicit)",
"pushoversounds bike": "Bicicletă",
"pushoversounds bugle": "Goarnă",
"pushoversounds cashregister": "Casă de marcat",
"pushoversounds classical": "Clasic",
"pushoversounds cosmic": "Cosmic",
"pushoversounds falling": "Cădere",
"pushoversounds gamelan": "Gamelan",
"pushoversounds incoming": "Sosire",
"pushoversounds intermission": "Pauză",
"pushoversounds magic": "Magie",
"pushoversounds mechanical": "Mecanic",
"pushoversounds tugboat": "Remorcher",
"pushoversounds alien": "Alarmă Extraterestră (lung)",
"pushoversounds climb": "Urcare (lung)",
"pushoversounds echo": "Ecou Pushover (lung)",
"pushoversounds updown": "Sus Jos (lung)",
"pushoversounds vibrate": "Doar Vibrații",
"pushoversounds none": "Niciunul (silențios)",
"pushyAPIKey": "Cheie API secretă",
"pushyToken": "Token dispozitiv",
"discord": "Discord",
"teams": "Microsoft Teams",
"signal": "Signal",
"slack": "Slack",
"rocket.chat": "Rocket.Chat",
"pushover": "Pushover",
"pushy": "Pushy",
"PushByTechulus": "Pushy by Techulus",
"octopush": "Octopush",
"promosms": "PromoSMS",
"lunasea": "LunaSea",
"apprise": "Apprise (Suportă 50+ Servicii de Notificare)",
"GoogleChat": "Google Chat (Doar Google Workspace)",
"pushbullet": "Pushbullet",
"Kook": "Kook",
"Guild ID": "ID-ul Breslei (Guild-ului)",
"line": "Line Messenger",
"mattermost": "Mattermost",
"User Key": "Cheie Utilizator",
"Device": "Dispozitiv",
"Message Title": "Titlu Mesaj",
"Notification Sound": "Sunet Notificare",
"More info on:": "Mai multe informații la: {0}",
"pushoverDesc2": "Dacă vrei să trimiți notificări la dispozitive diferite, completează câmpul „Dispozitiv”",
"Settings": "Setări",
"New Update": "Update Nou",
"Language": "Limbă",
"Game": "Joc",
"Primary Base URL": "URL-ul de Bază",
"List": "Listă",
"Add": "Adaugă",
"Add New Monitor": "Adaugă Monitor Nou",
"Pending": "În așteptare",
"Unknown": "Necunoscut",
"Specific Monitor Type": "Monitor de Tip Specific",
"pauseDashboardHome": "Pauză",
"Current": "Curent",
"-hour": "-oră",
"Response": "Răspuns",
"Heartbeat Interval": "Interval Heartbeat",
"Resend Notification if Down X times consequently": "Retrimite Notificarea dacă se Întâmpină Eroarea de X ori consecutiv",
"retriesDescription": "Numărul Maxim de Reîncercări înainte ca serviciul să fie marcat offline și să se trimită o notificare",
"maxRedirectDescription": "Numărul maxim de redirecționări permise. Setează la „0” pentru a dezactiva redirecționările.",
"Theme - Heartbeat Bar": "Temă - Bara de Heartbeat",
"Discourage search engines from indexing site": "Descurajează Motoarele de Căutare din a Indexa Acest Site",
"disableauth.message2": "Este proiectat pentru scenarii <strong>în care intenționezi să implementezi soluții terțe de autentificare</strong> în fața Uptime Kuma, cum ar fi Cloudflare Access, Authelia, sau alt mecanism de autentificare.",
"Login": "Logare",
"Notification Type": "Tipul Notificării",
"Email": "Email",
"Test": "Test",
"Certificate Info": "Informațiile Certificatului",
"Resolver Server": "Server-ul de Rezolvare",
"Last Result": "Ultimul Rezultat",
"notAvailableShort": "N/A",
"Default enabled": "Implicit activat",
"Create": "Creează",
"Schedule maintenance": "Programează Mentenanță",
"Select status pages...": "Selectează pagina de status…",
"alertNoFile": "Te rog selectează un fișier de importat.",
"alertWrongFileType": "Te rog selectează un fișier de tip JSON.",
"Clear all statistics": "Șterge toate Statisticile",
"Setup 2FA": "Configurează Autentificarea în Doi Pași",
"Two Factor Authentication": "Autentificare în Doi Pași",
"Inactive": "Inactiv",
"Add New below or Select...": "Adaugă Nou Mai Jos sau Selectează…",
"Pink": "Roz",
"Search...": "Caută…",
"Avg. Ping": "Ping Mediu",
"Avg. Response": "Timp de Răspuns Mediu",
"statusPageNothing": "Nimic aici, te rog adaugă un grup sau un monitor.",
"Go to Dashboard": "Mergi la Panoul de Control",
"webhookJsonDesc": "{0} este bun pentru orice server HTTP modern cum ar fi Express.js",
"webhookAdditionalHeadersDesc": "Setează antete adiționale trimise împreună cu webhook-ul.",
"HeadersInvalidFormat": "Formatul header-urilor de request nu este valid: ",
"clearDataOlderThan": "Păstrează istoricul monitorului pentru {0} zile.",
"records": "înregistrări",
"steamApiKeyDescription": "Pentru a monitoriza un server de joc Steam, ai nevoie de un o cheie pentru „Web-API„-ul Steam. Poți înregistra o astfel de cheie aici: ",
"recent": "Recent",
"Steam API Key": "Cheia API Steam",
"Pick a RR-Type...": "Alege un Tip-RR…",
"Pick Accepted Status Codes...": "Alege Codurile de Status Acceptate…",
"Create Incident": "Creează un Incident",
"primary": "implicit",
"light": "luminos",
"Please input title and content": "Te rog adaugă un titlu și conținut",
"Created": "Creat",
"Switch to Dark Theme": "Schimbă la Tema Întunecată",
"Add one": "Adaugă unul",
"No Monitors": "Niciun monitor",
"Untitled Group": "Grup fără nume",
"Services": "Servicii",
"shrinkDatabaseDescription": "Declanșează database VACUUM pentru SQLite. Dacă baza ta de date a fost creată după 1.10.0, AUTO_VACUUM este deja activat și această acțiune nu este necesară.",
"proxyDescription": "Proxy-urile trebuie să fie atribuite unui monitor pentru a funcționa.",
"enableProxyDescription": "Acest proxy nu va afecta cererile monitoarelor până este activat. Poți dezactiva temporar proxy-ul pentru toate monitoarele.",
"setAsDefaultProxyDescription": "Acest proxy va fi activat implicit pentru toate monitoarele noi. Poți totuși să îl dezactivezi separat pentru fiecare monitor.",
"Not installed": "Neinstalat",
"Accept characters:": "Acceptă caractere:",
"The slug is already taken. Please choose another slug.": "Acest slug este deja luat. Te rog alege alt slug.",
"Don't know how to get the token? Please read the guide:": "Nu știi cum să obții token-ul? Te rog citește acest ghid:",
"The current connection may be lost if you are currently connecting via Cloudflare Tunnel. Are you sure want to stop it? Type your current password to confirm it.": "Conexiunea curentă s-ar putea pierde dacă ești în proces de conectare printr-un tunel Cloudflare. Ești sigur că vrei să îl oprești? Tastează-ți parola curentă pentru a confirma.",
"Certificate Expiry Notification": "Notificare cu privire la expirarea certificatului",
"Show update if available": "Arată actualizarea dacă e disponibilă",
"The resource is no longer available.": "Această resursă nu mai este disponibilă.",
"certificationExpiryDescription": "Monitoarele HTTPS declanșează notificarea când certificatul TLS expiră în:",
"Docker Hosts": "Docker Hosts",
"supportTelegramChatID": "Suport Mesaje Directe / Grup / ID-ul Canalului de Text",
"wayToGetTelegramChatID": "Poți obține ID-ul chat-ului prin trimiterea unui mesaj către robot și mergând la acest URL pentru a vedea chat_id:",
"trustProxyDescription": "Ai incredere in antetele 'X-Forwarded-*'. Dacă vrei să obții IP-ul corect al client-ului și Uptime Kuma este în spatele unui proxy, cum ar fi Nginx sau Apache, trebuie să activezi asta.",
"Long-Lived Access Token can be created by clicking on your profile name (bottom left) and scrolling to the bottom then click Create Token. ": "Token-ul de acces cu durată de viață mare poate fi creat dacă dai click pe numele tău de profil (stânga jos) și prin derularea până la capătul paginii și click pe „Creează Token”. ",
"Notification Service": "Serviciu de Notificări",
"A list of Notification Services can be found in Home Assistant under \"Developer Tools > Services\" search for \"notification\" to find your device/phone name.": "O listă cu serviciile de notificare poate fi găsită în Home Assistant sub „Opțiuni Dezvoltator > Servicii” caută „notificare” pentru a găsi numele dispozitivului/telefonului.",
"backupOutdatedWarning": "Depășit: Pentru că au fost adăugate multe funcționalități, iar această funcție de backup este neîntreținută, nu poate genera sau restaura un backup complet.",
"lastDay4": "Răsantepenultima zi a Lunii",
"Display Timezone": "Afișează Fusul Orar",
"dnsCacheDescription": "Nu funcționează in anumite medii IPv6, dezactivează dacă întâmpini probleme.",
"Single Maintenance Window": "Fereastră unică de timp pentru mentennanță",
"Maintenance Time Window of a Day": "Fereastra de timp alocată pentru mentenanță dintr-o zi",
"uninstalling": "Dezinstalare",
"Ignore TLS Error": "Ignoră erorile TLS",
"wayToGetDiscordURL": "Poți obține asta mergând în Setări Server -> Integrări -> Vezi Webhook-urile -> Webhook nou",
"wayToCheckSignalURL": "Poți verifica acest URL pentru a vizualiza cum să configurezi unul:",
"wayToGetLineChannelToken": "Pentru început, accesează {0}, creează un furnizor și canal (API-ul Mesageriei), apoi poți obține token-ul de acces al canalului si ID-ul utilizatorului din itemii de meniu mentionati mai sus.",
"aboutIconURL": "Poți furniza un link către o pictogramă la secțiunea „URL-ul Pictogramei” pentru a suprascrie imaginea de profil implicită. Nu va fi folosită dacă există un emoticon configurat deja.",
"Channel Name": "Nume Canal",
"aboutMattermostChannelName": "Poți suprascrie canalul implicit pe care Webhook-ul îl folosește prin introducerea numelui canalului în câmpul „Nume Canal”. Acesta trebuie să fie activat în setările Webhook-ului Mattermost. Ex: #alt-canal",
"acceptedStatusCodesDescription": "Selectează codurile de status care sunt considerate un răspuns de succes.",
"deleteNotificationMsg": "Ești sigur că vrei să ștergi această notificare pentru toate monitoarele?",
"enableDefaultNotificationDescription": "Această notificare va fi activată implicit pentru toate monitoarele noi. Poți totuși să o dezactivezi individual pentru fiecare monitor.",
"importHandleDescription": "Alege „Sari Existente” dacă vrei să sari peste fiecare monitor sau notificare cu același nume. „Suprascrie” va șterge toate monitoarele și notificările existente.",
"confirmDisableTwoFAMsg": "Ești sigur că vrei să dezactivezi Autentificarea în Doi Pași?",
"affectedStatusPages": "Afișează acest mesaj de mentenanță pe paginile de status selectate",
"keywordDescription": "Caută cuvântul cheie în HTML simplu sau JSON. Această căutare ține cont de majuscule.",
"backupDescription3": "Datele importante, cum ar fi token-urile notificărilor sunt incluse în fișierul exportat; te rog stochează-l în siguranță.",
"pushoversounds pianobar": "Pian",
"pushoversounds siren": "Sirenă",
"pushoversounds spacealarm": "Alarmă Spațială",
"pushoversounds persistent": "Persistent (lung)",
"gotify": "Gotify",
"clicksendsms": "ClickSend SMS",
"wayToGetKookBotToken": "Creează o aplicație și obține token-ul robot la {0}",
"wayToGetKookGuildID": "Activează „Modul Dezvoltator” în setările Kook și dă click pe breaslă (guild) pentru a-i obține ID-ul",
"pushoverDesc1": "Prioritate de urgență (2) are o pauză implicită de 30 de secunde între reîncercări și expiră după o oră."
}

@ -43,7 +43,7 @@
"Delete": "Удалить",
"Current": "Текущий",
"Uptime": "Аптайм",
"Cert Exp.": "Сертификат истекает",
"Cert Exp.": "Сертификат истекает.",
"day": "день | дней",
"-day": " дней",
"hour": "час",
@ -74,7 +74,7 @@
"Bottom": "Снизу",
"None": "Отсутствует",
"Timezone": "Часовой пояс",
"Search Engine Visibility": "Индексация поисковыми системами:",
"Search Engine Visibility": "Индексация поисковыми системами",
"Allow indexing": "Разрешить индексирование",
"Discourage search engines from indexing site": "Запретить индексирование",
"Change Password": "Сменить пароль",
@ -86,7 +86,7 @@
"Enable Auth": "Включить авторизацию",
"disableauth.message1": "Вы уверены, что хотите <strong>отключить авторизацию</strong>?",
"disableauth.message2": "Это подходит для <strong>тех, у кого стоит другая авторизация</strong> перед открытием Uptime Kuma, например Cloudflare Access.",
"Please use this option carefully!": "Пожалуйста, используйте с осторожностью.",
"Please use this option carefully!": "Пожалуйста, используйте с осторожностью!",
"Logout": "Выйти",
"Leave": "Отмена",
"I understand, please disable": "Я понимаю, всё равно отключить",
@ -156,7 +156,7 @@
"Options": "Опции",
"Keep both": "Не проверять",
"Tags": "Теги",
"Add New below or Select...": "Добавить новый или выбрать...",
"Add New below or Select...": "Добавить новый или выбрать",
"Tag with this name already exist.": "Такой тег уже существует.",
"Tag with this value already exist.": "Тег с таким значением уже существует.",
"color": "цвет",
@ -169,7 +169,7 @@
"Indigo": "Индиго",
"Purple": "Пурпурный",
"Pink": "Розовый",
"Search...": "Поиск...",
"Search...": "Поиск",
"Avg. Ping": "Среднее значение пинга",
"Avg. Response": "Среднее время ответа",
"Entry Page": "Главная страница",
@ -208,7 +208,7 @@
"mattermost": "Mattermost",
"Primary Base URL": "Основной URL",
"Push URL": "URL пуша",
"needPushEvery": "К этому URL необходимо обращаться каждые {0} секунд",
"needPushEvery": "К этому URL необходимо обращаться каждые {0} секунд.",
"pushOptionalParams": "Опциональные параметры: {0}",
"defaultNotificationName": "Моё уведомление {notification} ({number})",
"here": "здесь",
@ -233,12 +233,12 @@
"smtpCC": "Копия",
"smtpBCC": "Скрытая копия",
"Discord Webhook URL": "Discord вебхук URL",
"wayToGetDiscordURL": "Вы можете создать его в Параметрах сервера -> Интеграции -> Создать вебхук",
"wayToGetDiscordURL": "Вы можете создать его в \"Настройки -> Интеграции -> Создать Вебхук\"",
"Bot Display Name": "Отображаемое имя бота",
"Prefix Custom Message": "Свой префикс сообщения",
"Hello @everyone is...": "Привет {'@'}everyone это...",
"Hello @everyone is...": "Привет {'@'} всем это…",
"Webhook URL": "URL вебхука",
"wayToGetTeamsURL": "Как создать URL вебхука вы можете узнать здесь - {0}.",
"wayToGetTeamsURL": "Как создать URL Вебхука вы можете узнать здесь - {0}.",
"Number": "Номер",
"Recipients": "Получатели",
"needSignalAPI": "Вам необходим клиент Signal с поддержкой REST API.",
@ -270,7 +270,7 @@
"octopushPhoneNumber": "Номер телефона (межд. формат, например: +79831234567) ",
"octopushSMSSender": "Имя отправителя SMS: 3-11 символов алвафита, цифр и пробелов (a-zA-Z0-9)",
"LunaSea Device ID": "ID устройства LunaSea",
"Apprise URL": "Apprise URL",
"Apprise URL": "Ссылка Уведомления",
"Example:": "Пример: {0}",
"Read more:": "Подробнее: {0}",
"Status:": "Статус: {0}",
@ -286,7 +286,7 @@
"Messaging API": "API сообщений",
"wayToGetLineChannelToken": "Сначала зайдите в {0}, создайте провайдера и канал (API сообщений), затем вы сможете получить токен доступа канала и ID пользователя из вышеупомянутых пунктов меню.",
"Icon URL": "URL иконки",
"aboutIconURL": "Вы можете предоставить ссылку на иконку в поле \"URL иконки\" чтобы переопределить картинку профиля по умолчанию. Не используется, если задана иконка Emoji.",
"aboutIconURL": "Вы можете вставить ссылку на иконку в поле \"URL иконки\" чтобы изменить картинку профиля по умолчанию. Не используется, если задана иконка Emoji.",
"aboutMattermostChannelName": "Вы можете переопределить канал по умолчанию, в который вебхук пишет, введя имя канала в поле \"Имя канала\". Это необходимо включить в настройках вебхука Mattermost. Например: #other-channel",
"matrix": "Matrix",
"promosmsTypeEco": "SMS ECO - дёшево и медленно, часто перегружен. Только для получателей из Польши.",
@ -315,8 +315,8 @@
"Certificate Chain": "Цепочка сертификатов",
"Valid": "Действительный",
"Hide Tags": "Скрыть тэги",
"Title": "Название инцидента:",
"Content": "Содержание инцидента:",
"Title": "Название инцидента",
"Content": "Содержание инцидента",
"Post": "Опубликовать",
"Cancel": "Отмена",
"Created": "Создано",
@ -327,7 +327,7 @@
"6h": "6 часов",
"24h": "24 часа",
"1w": "1 неделя",
"No monitors available.": "Нет доступных мониторов",
"No monitors available.": "Нет доступных мониторов.",
"Add one": "Добавить новый",
"Backup": "Резервная копия",
"Security": "Безопасность",
@ -363,8 +363,8 @@
"Done": "Готово",
"Info": "Инфо",
"Steam API Key": "Steam API-Ключ",
"Pick a RR-Type...": "Выберите RR-Тип...",
"Pick Accepted Status Codes...": "Выберите принятые коды состояния...",
"Pick a RR-Type...": "Выберите RR-Тип",
"Pick Accepted Status Codes...": "Выберите принятые коды состояния",
"Default": "По умолчанию",
"Please input title and content": "Пожалуйста, введите название и содержание",
"Last Updated": "Последнее Обновление",
@ -417,7 +417,7 @@
"Bark Group": "Bark Group",
"Bark Sound": "Bark Sound",
"WebHookUrl": "WebHookUrl",
"SecretKey": "SecretKey",
"SecretKey": "Секретный Ключ",
"For safety, must use secret key": "В целях безопасности необходимо использовать секретный ключ",
"Device Token": "Токен устройства",
"Platform": "Платформа",
@ -556,7 +556,7 @@
"Long-Lived Access Token can be created by clicking on your profile name (bottom left) and scrolling to the bottom then click Create Token. ": "Long-Lived Access Token can be created by clicking on your profile name (bottom left) and scrolling to the bottom then click Create Token. ",
"Notification Service": "Служба уведомлений",
"default: notify all devices": "по стандарту: уведомлять все устройства",
"A list of Notification Services can be found in Home Assistant under \"Developer Tools > Services\" search for \"notification\" to find your device/phone name.": "A list of Notification Services can be found in Home Assistant under \"Developer Tools > Services\" search for \"notification\" to find your device/phone name.",
"A list of Notification Services can be found in Home Assistant under \"Developer Tools > Services\" search for \"notification\" to find your device/phone name.": "Список служб уведомлений можно найти в Home Assistant в разделе \"Инструменты разработчика > Службы\", выполнив поиск по слову \"уведомление\", чтобы найти название вашего устройства/телефона.",
"Automations can optionally be triggered in Home Assistant:": "При желании автоматизацию можно активировать в Home Assistant.:",
"Trigger type:": "Тип триггера:",
"Event type:": "Тип события:",
@ -592,9 +592,78 @@
"Affected Monitors": "Затронутые мониторы",
"Start of maintenance": "Начало обслуживания",
"All Status Pages": "Все страницы статусов",
"Select status pages...": "Выберите страницу статуса...",
"resendEveryXTimes": "Повторная отправка каждые {0} раз",
"Select status pages...": "Выберите страницу статуса",
"resendEveryXTimes": "Повтор каждые {0} раз",
"resendDisabled": "Повторная отправка отключена",
"deleteMaintenanceMsg": "Вы действительно хотите удалить это обслуживание?",
"critical": "критично"
"critical": "критично",
"Custom Monitor Type": "Собственный тип монитора",
"markdownSupported": "Поддерживает синтаксис Markdown",
"Passive Monitor Type": "Пассивный тип монитора",
"Specific Monitor Type": "Специфичный тип монитора",
"Help": "Помощь",
"Game": "Игра",
"Resend Notification if Down X times consequently": "Повторно отправить уведомление, если не работает X раз подряд",
"General Monitor Type": "Основной тип монитора",
"weekdayShortWed": "Ср",
"weekdayShortThu": "Чт",
"weekdayShortFri": "Пт",
"weekdayShortSat": "Сб",
"weekdayShortSun": "Вс",
"dayOfMonth": "День месяца",
"Pick Affected Monitors...": "Выберите затронутые мониторы…",
"Custom": "Пользовательский",
"successMessage": "Сообщение об успехе",
"successMessageExplanation": "Сообщение MQTT, которое может рассматриваться как успешное",
"Custom CSS": "Пользовательские CSS",
"weekdayShortTue": "Вт",
"dayOfWeek": "День недели",
"confirmDeleteTagMsg": "Вы уверены, что хотите удалить этот тег? Мониторы с этим тегом удалены не будут.",
"loadingError": "Невозможно получить данные, пожалуйста попробуйте позже.",
"Packet Size": "Размер пакета",
"warningTimezone": "Используется часовой пояс сервера",
"weekdayShortMon": "Пн",
"ZohoCliq": "ZohoCliq",
"strategyManual": "Активен/Неактивен Вручную",
"lastDay": "Последний день",
"lastDay1": "Последний день месяца",
"lastDay2": "Второй последний день месяца",
"lastDay3": "Третий последний день месяца",
"lastDay4": "Четвертый последний день месяца",
"No Maintenance": "Ничего не обслуживается",
"pauseMaintenanceMsg": "Вы уверены что хотите поставить на паузу?",
"maintenanceStatus-under-maintenance": "На техобслуживании",
"maintenanceStatus-inactive": "Неактивен",
"maintenanceStatus-scheduled": "Запланирован(о)",
"maintenanceStatus-ended": "Закончился(ось)",
"maintenanceStatus-unknown": "Неизвестен",
"Display Timezone": "Показать часовой пояс",
"Server Timezone": "Часовой пояс сервера",
"statusPageMaintenanceEndDate": "Конец",
"IconUrl": "URL Иконки",
"Enable DNS Cache": "Включить DNS кэш",
"Enable": "Включить",
"Disable": "Отключить",
"Single Maintenance Window": "Единое Окно Обслуживания",
"Schedule Maintenance": "Запланировать обслуживание",
"Date and Time": "Дата и Время",
"DateTime Range": "Промежуток Даты и Времени",
"uninstalling": "Удаляется",
"dataRetentionTimeError": "Период хранения должен быть равен 0 или больше",
"infiniteRetention": "Установите 0 для бессрочного хранения.",
"enableGRPCTls": "Разрешить отправлять gRPC запрос через TLS соединение",
"Free Mobile API Key": "API ключ Free Mobile",
"Edit Tag": "Редактировать тэг",
"webhookAdditionalHeadersDesc": "Устанавливает дополнительные заголовки, отправляемые с помощью веб-хука.",
"topic": "Тема",
"Customize": "Персонализировать",
"Custom Footer": "Пользовательский footer",
"dnsCacheDescription": "Это может не работать на некоторых IPv6 окружениях, отключите это, если у вас возникают проблемы.",
"confirmUninstallPlugin": "Вы уверены, что хотите удалить этот плагин?",
"plugin": "Плагин | Плагины",
"install": "Установить",
"installing": "Устанавливается",
"uninstall": "Удалить",
"Recurring": "Повторяющийся",
"recurringInterval": "Интервал"
}

@ -0,0 +1,25 @@
{
"Settings": "Opsione",
"Dashboard": "FaqeKryesore",
"Help": "Ndihma",
"Language": "Gjuha",
"Appearance": "Paraqitja",
"Theme": "Theme",
"General": "Te pergjithshme",
"Game": "Loje",
"Primary Base URL": "ULR Baze Primare",
"List": "List",
"Add": "Shto",
"Add New Monitor": "Shto Monitor te Ri",
"Quick Stats": "Statistika Flash",
"Up": "Lart",
"Down": "Poshte",
"Pending": "Ne Pritje",
"statusMaintenance": "Mirembatje",
"Maintenance": "Mirembajtje",
"Unknown": "Panjohur",
"languageName": "Shqip",
"New Update": "Update i ri",
"Version": "Version",
"Check Update On GitHub": "Kontrollo Update ne GitHub"
}

@ -102,7 +102,7 @@
"Disable Auth": "ปิดใช้งานการตรวจสอบสิทธิ์",
"Enable Auth": "เปิดใช้งานการตรวจสอบสิทธิ์",
"disableauth.message1": "คุณต้องการที่จะ <strong>ปิดใช้งานระบบรับรองความถูกต้องใช่หรือไม่</strong>?",
"disableauth.message2": "ระบบนี้ถูกออกแบบมาเพื่อการใช้งานกับระบบรับรองความถูกต้องของบุคคลที่สามเช่น Cloudflare Access, Authelia หรือวิธีการอื่น ๆ",
"disableauth.message2": "ระบบนี้ถูกออกแบบมาเพื่อการใช้งานกับระบบรับรองความถูกต้องของบุคคลที่สามเช่น Cloudflare Access, Authelia หรือวิธีการอื่นๆ",
"Please use this option carefully!": "โปรดใช้ความระมัดระวังในการเลือกใช้งานระบบนี้ !",
"Logout": "ออกจากระบบ",
"Leave": "ออก",
@ -159,7 +159,7 @@
"Token": "กุญแจ",
"Show URI": "แสดง URI",
"Tags": "แท็ก",
"Add New below or Select...": "เพิ่มใหม่ด้านล่างหรือเลือก...",
"Add New below or Select...": "เพิ่มใหม่ด้านล่างหรือเลือก",
"Tag with this name already exist.": "แท็กที่มีชื่อนี้มีอยู่แล้ว",
"Tag with this value already exist.": "แท็กที่มีข้อมูลนี้มีอยู่แล้ว",
"color": "สี",
@ -172,7 +172,7 @@
"Indigo": "ม่วง",
"Purple": "ม่วง",
"Pink": "ชมพู",
"Search...": "ค้นหา...",
"Search...": "ค้นหา",
"Avg. Ping": "ค่า Ping เฉลี่ย",
"Avg. Response": "ค่า Response เฉลี่ย",
"Entry Page": "หน้าต้อนรับ",
@ -217,7 +217,7 @@
"wayToGetDiscordURL": "คุณสามารถรับได้โดยการไปที่ Server Settings -> Integrations -> Create Webhook",
"Bot Display Name": "ชื่อบอท",
"Prefix Custom Message": "คำนำหน้าข้อความที่กำหนดเอง",
"Hello @everyone is...": "สวัสดี {'@'}everyone นี่...",
"Hello @everyone is...": "สวัสดี {'@'}everyone นี่",
"teams": "Microsoft Teams",
"Webhook URL": "Webhook URL",
"wayToGetTeamsURL": "คุณสามารถเรียนรู้วิธีการสร้าง Webhook URL {0}",
@ -303,7 +303,7 @@
"Body": "เนื้อหา",
"Headers": "ส่วนหัว",
"PushUrl": "Push URL",
"HeadersInvalidFormat": "เนื้อหาคำขอส่วนหัวไม่ใช่ JSON ที่ถูกต้อง :",
"HeadersInvalidFormat": "เนื้อหาคำขอส่วนหัวไม่ใช่ JSON ที่ถูกต้อง: ",
"BodyInvalidFormat": "เนื้อหาคำขอไม่ใช่ JSON ที่ถูกต้อง : ",
"Monitor History": "ประวัติมอนิเตอร์",
"clearDataOlderThan": "เก็บข้อมูลมอนิเตอร์ {0} วัน",
@ -323,7 +323,7 @@
"Steam API Key": "Steam API Key",
"Shrink Database": "ย่อฐานข้อมูล",
"Pick a RR-Type...": "เลือกชนิด DNS Record",
"Pick Accepted Status Codes...": "เลือกสถานะที่ยอมรับ...",
"Pick Accepted Status Codes...": "เลือกเลขสถานะที่ยอมรับ…",
"Default": "ค่าเริ่มต้น",
"HTTP Options": "ตัวเลือก HTTP",
"Create Incident": "สร้างเหตุการณ์",
@ -441,9 +441,9 @@
"wayToGetCloudflaredURL": "(ดาวโหลด cloudflared จาก {0})",
"cloudflareWebsite": "เว็บไซต์ Cloudflare",
"Message:": "ข้อความ :",
"Don't know how to get the token? Please read the guide:": "ไม่รู้วิธีการรับกุญแจ?, กรุณาอ่านคู่มือ",
"Don't know how to get the token? Please read the guide:": "ไม่รู้วิธีการรับกุญแจ? กรุณาอ่านคู่มือ:",
"The current connection may be lost if you are currently connecting via Cloudflare Tunnel. Are you sure want to stop it? Type your current password to confirm it.": "การเชื่อมต่อปัจุบันอาจขาดหายหากคุณกำลังเชื่อมต่อ Cloudflare Tunnel คุณแน่ใจหรือไม่ที่จะหยุด, พิมรหัสผ่านของคุณเพื่อยืนยัน",
"Other Software": "ซอฟต์แวร์อื่นๆ ",
"Other Software": "ซอฟต์แวร์อื่นๆ",
"For example: nginx, Apache and Traefik.": "เช่น: nginx, Apache และ Traefik",
"Please read": "กรุณาอ่าน",
"Subject:": "เรื่อง :",
@ -455,7 +455,7 @@
"Domain Name Expiry Notification": "แจ้งเตือนการหมดอายุของโดเมน",
"Proxy": "Proxy",
"Date Created": "วันที่สร้าง",
"onebotHttpAddress": "ที่อยู่ HTTP OneBot ",
"onebotHttpAddress": "ที่อยู่ HTTP OneBot",
"onebotMessageType": "ชนิดข้อความ OneBot",
"onebotGroupMessage": "กลุ่ม",
"onebotPrivateMessage": "ส่วนตัว",
@ -522,7 +522,7 @@
"resendEveryXTimes": "ส่งซ้ำทุก {0} ครั้ง",
"resendDisabled": "การส่งซ้ำถูกปิดใช้งาน",
"dnsPortDescription": "พอร์ตของเซิร์ฟเวอร์ DNS, ค่าเริ่มต้นคือ 53, คุณสามารถเปลี่ยนพอร์ตตอนไหนก็ได้",
"Resend Notification if Down X times consequently": "ส่งการแจ้งเตือนซ้ำถ้าออฟไลน์ครบ X ครั้ง",
"Resend Notification if Down X times consecutively": "ส่งการแจ้งเตือนซ้ำถ้าออฟไลน์ครบ X ครั้ง",
"error": "เกิดข้อผิดพลาด",
"critical": "วิกฤต",
"wayToGetPagerDutyKey": "คุณสามารถรับคีย์ได้โดยการไปที่ Service -> Service Directory -> (Select a service) -> Integrations -> Add integration, และค้นหา \"Events API V2\", สำหรับข้อมูลเพิ่มเติม {0}",
@ -562,11 +562,11 @@
"Domain": "โดเมน",
"Workstation": "Workstation",
"disableCloudflaredNoAuthMsg": "คุณอยู่ในโหมดไม่มีการตรวจสอบสิทธิ์, ไม่จำเป็นต้องมีรหัสผ่าน",
"trustProxyDescription": "เชื่อ Header 'X-Forwarded-*' ถ้าคุณต้องการไอพีที่ถูกต้องและ Uptime Kuma อยู่ข้างหลัง Nginx หรือ Apache, คุณควรเปิดใช้งาน",
"trustProxyDescription": "เชื่อ Header 'X-Forwarded-*', คุณควรเปิดใช้งาน ถ้าคุณต้องการ IP ของผู้ใช้ที่ถูกต้องและ Uptime Kuma อยู่ข้างหลัง Nginx หรือ Apache",
"Examples": "ตัวอย่าง",
"Home Assistant URL": "Home Assistant URL",
"Long-Lived Access Token": "Access Token แบบมีอายุนาน",
"Long-Lived Access Token can be created by clicking on your profile name (bottom left) and scrolling to the bottom then click Create Token. ": "Access Token แบบมีอายุนานสามารถสร้างได้โดยคลิกชื่อบนโปรไฟล์ (ล่างซ้าย) และเลื่อนไปข้างล่างจากนั้นคลิก \"Create Token\"",
"Long-Lived Access Token can be created by clicking on your profile name (bottom left) and scrolling to the bottom then click Create Token. ": "Access Token แบบมีอายุนานสามารถสร้างได้โดยคลิกชื่อบนโปรไฟล์ (ล่างซ้าย) และเลื่อนไปข้างล่างจากนั้นคลิก \"Create Token\" ",
"Notification Service": "บริการแจ้งเตือน",
"default: notify all devices": "ค่าเริ่มต้น: แจ้งเตือนทุกอุปกรณ์",
"A list of Notification Services can be found in Home Assistant under \"Developer Tools > Services\" search for \"notification\" to find your device/phone name.": "รายการแจ้งเตือนสามารถหาได้ใน Home Assistant ในเมนู \"Developer Tools > Services\" แล้วค้นหา \"notification\" เพื่อหาชื่ออุปกรณ์หรือชื่อโทรศัพท์",
@ -576,5 +576,30 @@
"Event data:": "ข้อมูลกิจกรรม:",
"Then choose an action, for example switch the scene to where an RGB light is red.": "จากนั้นเลือกการกระทำ, ตัวอย่าง เช่น เปลี่ยนเป็นไฟสีแดง",
"Frontend Version": "เวอร์ชั่น Frontend",
"Frontend Version do not match backend version!": "เวอร์ชั่น Frontend ไม่ตรงกับ Backend !"
"Frontend Version do not match backend version!": "เวอร์ชั่น Frontend ไม่ตรงกับ Backend !",
"webhookAdditionalHeadersTitle": "Header เพิ่มเติม",
"webhookAdditionalHeadersDesc": "กำหนด Header ที่จะส่งไปหร้อมกับ Webhook",
"Start of maintenance": "เริ่มการซ่อมบำรุง",
"All Status Pages": "หน้าสถานะทั้งหมด",
"Custom": "กำหนดเอง",
"Game": "เกม",
"statusMaintenance": "การซ่อมบำรุง",
"Maintenance": "การซ่อมบำรุง",
"Monitor": "มอนิเตอร์ | มอนิเตอร์",
"Select status pages...": "เลือกหน้าสถานะ",
"Schedule maintenance": "กำหนดเวลาบำรุงรักษา",
"Affected Monitors": "มอนิเตอร์ที่ได้รับผลกระทบ",
"markdownSupported": "รองรับ Markdown",
"Help": "ช่วยเหลือ",
"Pick Affected Monitors...": "เลือกมอนิเตอร์ที่ได้รับผลกระทบ",
"Packet Size": "ขนาดของ Packet",
"ZohoCliq": "ZohoCliq",
"backupOutdatedWarning": "ไม่ได้รับการพัฒนาแล้ว : ไม่สามารถสร้างหรือกูข้อมูลสำรองได้สมบูรณ์ เนื่องจากมีฟีเจอร์ใหม่เพิ่มขึ้นมากและการแบ็คอัพไม่ได้ถูกพัฒนา",
"backupRecommend": "กรุณาแบ็คอัพข้อมูลทั้งหมดหรือโฟลเดอร์ Data (./data/) โดยตรงแทน",
"Optional": "ไม่จำเป็น",
"squadcast": "Squadcast",
"or": "หรือ",
"recurringInterval": "ช่วงเวลา",
"Recurring": "ทำซ้ำ",
"General Monitor Type": "ชนิดมอนิเตอร์ทั่วไป"
}

@ -74,7 +74,7 @@
"Heartbeat Interval": "Servis Test Aralığı",
"Retries": "Yeniden deneme",
"Heartbeat Retry Interval": "Sağlık Durumları Tekrar Deneme Sıklığı",
"Resend Notification if Down X times consequently": "Sonuç olarak X kez düşerse bildirimi yeniden gönder",
"Resend Notification if Down X times consecutively": "Art arda X kez düşerse bildirimi yeniden gönder",
"Advanced": "Gelişmiş",
"Upside Down Mode": "Ters/Düz Modu",
"Max. Redirects": "Maksimum Yönlendirme",
@ -217,7 +217,7 @@
"smtpBCC": "BCC",
"discord": "Discord",
"Discord Webhook URL": "Discord Webhook URL",
"wayToGetDiscordURL": "Bunu Sunucu Ayarları -> Entegrasyonlar -> Webhook Oluştur'a giderek alabilirsiniz.",
"wayToGetDiscordURL": "Bunu Sunucu Ayarları -> Entegrasyonlar -> Webhookları Görüntüle -> Yeni Webhook Oluştur adımını izleyerek alabilirsiniz.",
"Bot Display Name": "Botun Görünecek Adı",
"Prefix Custom Message": "Önek Özel Mesaj",
"Hello @everyone is...": "Merhaba {'@'}everyone…",
@ -448,7 +448,7 @@
"Message:": "Mesaj:",
"Don't know how to get the token? Please read the guide:": "Tokeni nasıl alacağınızı bilmiyor musunuz? Lütfen kılavuzu okuyun:",
"The current connection may be lost if you are currently connecting via Cloudflare Tunnel. Are you sure want to stop it? Type your current password to confirm it.": "Halihazırda Cloudflare Tüneli üzerinden bağlanıyorsanız mevcut bağlantı kesilebilir. Durdurmak istediğinden emin misin? Onaylamak için mevcut şifrenizi yazın.",
"HTTP Headers": "HTTP Headers",
"HTTP Headers": "HTTP Başlıkları",
"Trust Proxy": "Trust Proxy",
"Other Software": "Diğer Yazılımlar",
"For example: nginx, Apache and Traefik.": "Örneğin: nginx, Apache ve Traefik.",
@ -691,5 +691,10 @@
"promosms": "PromoSMS",
"lunasea": "LunaSea",
"line": "Line Messenger",
"mattermost": "Mattermost"
"mattermost": "Mattermost",
"markdownSupported": "Markdown yazım formatı desteklenir",
"Google Analytics ID": "Google Analytics ID",
"Edit Tag": "Etiketi Düzenle",
"Learn More": "Daha fazla bilgi edin",
"Server Address": "Sunucu Adresi"
}

@ -45,9 +45,9 @@
"Uptime": "Аптайм",
"Cert Exp.": "Сертифікат спливає",
"day": "день | днів",
"-day": " днів",
"-day": "днів",
"hour": "година",
"-hour": " години",
"-hour": "години",
"Response": "Відповідь",
"Ping": "Пінг",
"Monitor Type": "Тип монітора",
@ -74,7 +74,7 @@
"Bottom": "Знизу",
"None": "Відсутня",
"Timezone": "Часовий пояс",
"Search Engine Visibility": "Індексація пошуковими системами:",
"Search Engine Visibility": "Видимість для пошукових систем",
"Allow indexing": "Дозволити індексування",
"Discourage search engines from indexing site": "Заборонити індексування",
"Change Password": "Змінити пароль",
@ -86,7 +86,7 @@
"Enable Auth": "Увімкнути авторизацію",
"disableauth.message1": "Ви впевнені, що бажаєте <strong>вимкнути авторизацію</strong>?",
"disableauth.message2": "Це підходить для <strong>тих, у кого встановлена інша авторизація</strong> пееред відкриттям Uptime Kuma, наприклад Cloudflare Access.",
"Please use this option carefully!": "Будь ласка, використовуйте з обережністю.",
"Please use this option carefully!": "Будь ласка, використовуйте з обережністю!",
"Logout": "Вийти",
"Leave": "Відміна",
"I understand, please disable": "Я розумію, все одно відключити",
@ -156,7 +156,7 @@
"Options": "Опції",
"Keep both": "Не перевіряти",
"Tags": "Теги",
"Add New below or Select...": "Додати новий або вибрати...",
"Add New below or Select...": "Додати новий або вибрати",
"Tag with this name already exist.": "Такий тег вже існує.",
"Tag with this value already exist.": "Тег із таким значенням вже існує.",
"color": "колір",
@ -169,7 +169,7 @@
"Indigo": "Індиго",
"Purple": "Пурпурний",
"Pink": "Рожевий",
"Search...": "Пошук...",
"Search...": "Пошук",
"Avg. Ping": "Середній пінг",
"Avg. Response": "Середній час відповіді",
"Entry Page": "Головна сторінка",
@ -208,8 +208,8 @@
"mattermost": "Mattermost",
"Primary Base URL": "Основна URL",
"Push URL": "URL пуша",
"needPushEvery": "До цієї URL необхідно звертатися кожні {0} секунд",
"pushOptionalParams": "Опціональні параметри: {0}",
"needPushEvery": "Цю URL необхідно викликати кожні {0} секунд",
"pushOptionalParams": "Додаткові параметри: {0}",
"defaultNotificationName": "Моє сповіщення {notification} ({number})",
"here": "тут",
"Required": "Потрібно",
@ -362,8 +362,8 @@
"Done": "Готово",
"Info": "Інфо",
"Steam API Key": "Steam API-Ключ",
"Pick a RR-Type...": "Виберіть RR-тип...",
"Pick Accepted Status Codes...": "Виберіть прийняті коди стану...",
"Pick a RR-Type...": "Виберіть RR-тип",
"Pick Accepted Status Codes...": "Виберіть прийняті коди стану",
"Default": "За замовчуванням",
"Please input title and content": "Будь ласка, введіть назву та зміст",
"Last Updated": "Останнє Оновлення",
@ -526,5 +526,42 @@
"ntfy Topic": "ntfy Тема",
"Domain": "Домен",
"Workstation": "Робоча станція",
"disableCloudflaredNoAuthMsg": "Ви перебуваєте в режимі без авторизації, пароль не потрібен."
"disableCloudflaredNoAuthMsg": "Ви перебуваєте в режимі без авторизації, пароль не потрібен.",
"Schedule maintenance": "Графік обслуговування",
"Affected Monitors": "Задіяні монітори",
"HomeAssistant": "Home Assistant",
"smseaglePriority": "Пріоритет повідомлення (0-9, за замовчуванням = 0)",
"smseagleRecipient": "Отримувач(і) (декілька отримувачів повинні бути відокремлені комами)",
"markdownSupported": "Підтримується синтаксис розмітки",
"Resend Notification if Down X times consequently": "Повторно надсилати сповіщення, якщо падіння відбулося X разів підряд",
"resendEveryXTimes": "Повторно відправляти кожні {0} разів",
"resendDisabled": "Повторне надсилання вимкнено",
"Start of maintenance": "Початок обслуговування",
"Select status pages...": "Вибери сторінку стану…",
"All Status Pages": "Всі сторінки станів",
"Passive Monitor Type": "Пасивний моніторинг",
"Specific Monitor Type": "Специфічний моніторинг",
"Monitor": "Монітор | Монітори",
"smseagle": "SMSEagle",
"smseagleEncoding": "Надсилати в Unicode",
"smseagleUrl": "URL-адреса пристрою SMSEagle",
"smseagleToken": "Токен доступу API",
"smseagleRecipientType": "Тип одержувача",
"smseagleContact": "Телефонний контакт(и)",
"smseagleGroup": "Телефонна група(и)",
"smseagleTo": "Телефонний номер(и)",
"Help": "Допомога",
"Game": "Гра",
"Pick Affected Monitors...": "Виберіть задіяні монітори…",
"statusMaintenance": "Обслуговування",
"Maintenance": "Обслуговування",
"General Monitor Type": "Основний моніторинг",
"error": "Помилка",
"webhookAdditionalHeadersTitle": "Додаткові заголовки",
"webhookAdditionalHeadersDesc": "Задати додаткові заголовки, що за допомогою вебхука.",
"critical": "Критичний",
"Custom": "Нестандартний",
"successMessage": "Повідомлення про успіх",
"Customize": "Налаштувати",
"topic": "Тема"
}

@ -3,7 +3,7 @@
"checkEverySecond": "检测频率 {0} 秒",
"retryCheckEverySecond": "重试间隔 {0} 秒",
"resendEveryXTimes": "每 {0} 次失败则重复发送一次",
"resendDisabled": "为 0 时禁用重复发送",
"resendDisabled": "禁用重复发送",
"retriesDescription": "服务被标记为故障并发送通知之前的最大重试次数",
"ignoreTLSError": "忽略 HTTPS 站点的 TLS/SSL 错误",
"upsideDownModeDescription": "反转状态监控,如果服务可访问,则认为是故障。",
@ -60,7 +60,7 @@
"Quick Stats": "状态速览",
"Up": "正常",
"Down": "故障",
"Pending": "正在检测",
"Pending": "检测",
"Unknown": "未知",
"Pause": "暂停",
"Name": "名称",
@ -85,13 +85,13 @@
"Friendly Name": "显示名称",
"URL": "URL",
"Hostname": "主机名",
"Port": "端口",
"Port": "端口",
"Heartbeat Interval": "心跳间隔",
"Retries": "重试次数",
"Heartbeat Retry Interval": "心跳重试间隔",
"Resend Notification if Down X times consequently": "连续失败时重复发送通知的间隔次数",
"Resend Notification if Down X times consecutively": "连续失败时重复发送通知的间隔次数",
"Advanced": "高级",
"Upside Down Mode": "反转监控",
"Upside Down Mode": "反转模式",
"Max. Redirects": "最大重定向次数",
"Accepted Status Codes": "有效状态码",
"Push URL": "推送 URL",
@ -272,7 +272,6 @@
"apprise": "Apprise (支持 50+ 种通知服务)",
"GoogleChat": "Google Chat仅 Google Workspace",
"pushbullet": "Pushbullet",
"AliyunSMS": "阿里云短信服务",
"Kook": "Kook",
"wayToGetKookBotToken": "在 {0} 创建应用并获取机器人 Token",
"wayToGetKookGuildID": "在 Kook 设置中打开“开发者模式”,然后右键点击频道可获取其 ID",
@ -448,7 +447,6 @@
"Bark Endpoint": "Bark 接入点",
"Bark Group": "Bark 群组",
"Bark Sound": "Bark 铃声",
"DingDing": "钉钉自定义机器人",
"WebHookUrl": "钉钉自定义机器人 Webhook 地址",
"SecretKey": "钉钉自定义机器人加签密钥",
"For safety, must use secret key": "出于安全考虑,必须使用加签密钥",
@ -679,9 +677,9 @@
"high": "高价",
"General Monitor Type": "常规监控类型",
"Passive Monitor Type": "被动监控类型",
"Specific Monitor Type": "针对监控类型",
"Specific Monitor Type": "特殊监控类型",
"dataRetentionTimeError": "保留期必须为0或更大",
"Monitor": "监控项 | 监控项",
"Monitor": "监控项",
"Custom": "自定义",
"promosmsAllowLongSMS": "允许长的短信",
"confirmDeleteTagMsg": "你确定你要删除这个标签?与此标签关联的监视器不会被删除。",
@ -696,5 +694,9 @@
"uninstall": "卸载",
"uninstalling": "正在卸载",
"confirmUninstallPlugin": "您确定要卸载此插件吗?",
"Custom Monitor Type": "自定义监控类型"
"Custom Monitor Type": "自定义监控类型",
"markdownSupported": "支持 Markdown 语法",
"Google Analytics ID": "Google Analytics分析ID",
"Learn More": "了解更多",
"Edit Tag": "编辑标签"
}

@ -102,9 +102,9 @@
"deleteNotificationMsg": "是否確定刪除這個通知設定?如監測器啟用了這個通知,將會收不到通知。",
"Resolver Server": "DNS 伺服器",
"Resource Record Type": "DNS 記錄類型",
"resolverserverDescription": "預設為 Cloudflare DNS 伺服器,你可以轉用其他 DNS 伺服器。",
"resolverserverDescription": "預設為 Cloudflare DNS 伺服器,你可以轉用其他 DNS 伺服器。",
"rrtypeDescription": "請選擇 DNS 記錄類型",
"pauseMonitorMsg": "是否確定暫停?",
"pauseMonitorMsg": "是否確定暫停?",
"Last Result": "最後結果",
"Create your admin account": "建立管理員帳號",
"Repeat Password": "重複密碼",
@ -128,10 +128,10 @@
"backupDescription3": "此備份可能包含了一些敏感資料如通知裡的 Token請小心保存備份。",
"alertNoFile": "請選擇一個檔案",
"alertWrongFileType": "請選擇 JSON 檔案",
"twoFAVerifyLabel": "Please type in your token to verify that 2FA is working",
"tokenValidSettingsMsg": "Token is valid! You can now save the 2FA settings.",
"confirmEnableTwoFAMsg": "Are you sure you want to enable 2FA?",
"confirmDisableTwoFAMsg": "Are you sure you want to disable 2FA?",
"twoFAVerifyLabel": "請輸入 Token 以確認 2FA",
"tokenValidSettingsMsg": "Token 有效!您現在可以儲存 2FA 設定。",
"confirmEnableTwoFAMsg": "您確定要啟用 2FA 嗎?",
"confirmDisableTwoFAMsg": "您確定要停用 2FA 嗎?",
"Apply on all existing monitors": "套用至目前所有監測器",
"Verify Token": "驗証 Token",
"Setup 2FA": "設定 2FA",
@ -145,8 +145,8 @@
"Show URI": "顯示 URI",
"Clear all statistics": "清除所有歷史記錄",
"retryCheckEverySecond": "Retry every {0} seconds.",
"importHandleDescription": "Choose 'Skip existing' if you want to skip every monitor or notification with the same name. 'Overwrite' will delete every existing monitor and notification.",
"confirmImportMsg": "Are you sure to import the backup? Please make sure you've selected the right import option.",
"importHandleDescription": "\"略過已存在的\" 會跳過所有相同名稱的監測器或通知。 '覆蓋' 將刪除所有現有的監測器及通知。",
"confirmImportMsg": "您確定要匯入備份嗎?請確認你已選擇正確的匯入設定。",
"Heartbeat Retry Interval": "Heartbeat Retry Interval",
"Import Backup": "匯入備份",
"Export Backup": "匯出備份",
@ -360,7 +360,7 @@
"smtpDkimDesc": "請參考 Nodemailer DKIM {0} 使用方式。",
"documentation": "文件",
"smtpDkimDomain": "網域名稱",
"smtpDkimKeySelector": "DKIM 選取器",
"smtpDkimKeySelector": "Key Selector",
"smtpDkimPrivateKey": "私密金鑰",
"smtpDkimHashAlgo": "雜湊演算法 (選填)",
"smtpDkimheaderFieldNames": "要簽署的郵件標頭 (選填)",
@ -397,7 +397,7 @@
"affectedStatusPages": "在已選取的狀態頁中顯示此維護訊息",
"Primary Base URL": "主要 Base URL",
"Passive Monitor Type": "被動監測器類型",
"Resend Notification if Down X times consequently": "若 X 次心跳皆離線,重新傳送通知",
"Resend Notification if Down X times consecutively": "每 X 次心跳皆離線,重新傳送通知",
"Game": "遊戲",
"Specific Monitor Type": "特定監測器類型",
"Monitor": "監測器 | 監測器",
@ -573,5 +573,88 @@
"Maintenance Time Window of a Day": "每日維護時段",
"Proxy": "Proxy",
"backupOutdatedWarning": "過時:由於備份功能未顧及新功能的增加,因此備份功能無法產生或復原完整的備份。",
"Optional": "可選填"
"Optional": "可選填",
"markdownSupported": "支援 Markdown",
"Custom Monitor Type": "自訂監測器",
"Google Analytics ID": "Google Analytics ID",
"Learn More": "了解更多",
"Server Address": "Server 地址",
"Edit Tag": "編輯標籤",
"confirmDeleteTagMsg": "你確定你要刪除此標籤?相關的監測器不會被刪除。",
"pushoversounds pushover": "Pushover (預設)",
"pushoversounds tugboat": "Tug Boat",
"pushyToken": "裝置 Token",
"Proto Content": "Proto 內容",
"onebotHttpAddress": "OneBot HTTP 地址",
"HomeAssistant": "Home Assistant",
"Leave blank to use a shared sender number.": "留空以使用平台共享的發送人號碼。",
"auto acknowledged": "自動標記已讀",
"wayToGetPagerDutyKey": "您可以前往 Service -> Service Directory -> (Select a service) -> Integrations -> Add integration 以取得。您可以搜尋 \"Events API V2\"。詳細資訊 {0}",
"Kook": "Kook",
"wayToGetKookBotToken": "到 {0} 創建應用並取得 Bot Token",
"grpcMethodDescription": "Method 名稱將被轉換成 cammelCase 命名,如 sayHello、check 等。",
"deleteMaintenanceMsg": "您確定要刪除此維護嗎?",
"dnsPortDescription": "DNS 伺服器 port。預設為 53。您可以隨時變更 port。",
"atLeastOneMonitor": "選擇至少一個受影響的監測器",
"endpoint": "endpoint",
"octopushAPIKey": "在控制台的 HTTP API 憑證取得的 \"API Key\"",
"octopushLogin": "在控制台的 HTTP API 憑證取得的 \"Login\"",
"promosmsLogin": "API 登入名稱",
"promosmsPassword": "API 密碼",
"pushoversounds bike": "Bike",
"pushoversounds bugle": "Bugle",
"pushoversounds cashregister": "Cash Register",
"pushoversounds classical": "Classical",
"pushoversounds cosmic": "Cosmic",
"pushoversounds falling": "Falling",
"pushoversounds gamelan": "Gamelan",
"pushoversounds incoming": "Incoming",
"pushoversounds intermission": "Intermission",
"pushoversounds magic": "Magic",
"pushoversounds mechanical": "Mechanical",
"pushoversounds pianobar": "Piano Bar",
"pushoversounds siren": "Siren",
"pushoversounds spacealarm": "Space Alarm",
"pushoversounds alien": "Alien Alarm (long)",
"pushoversounds climb": "Climb (long)",
"pushoversounds persistent": "Persistent (long)",
"pushoversounds echo": "Pushover Echo (long)",
"pushoversounds updown": "Up Down (long)",
"pushoversounds vibrate": "Vibrate Only",
"pushoversounds none": "None (silent)",
"pushyAPIKey": "Secret API Key",
"Guild ID": "Guild ID",
"Strategy": "策略",
"Free Mobile User Identifier": "Free Mobile User Identifier",
"Free Mobile API Key": "Free Mobile API Key",
"Enable TLS": "使用 TLS",
"Proto Service Name": "Proto 服務名稱",
"Proto Method": "Proto 方式",
"onebotGroupMessage": "群組",
"onebotMessageType": "OneBot 訊息類型",
"ntfy Topic": "ntfy Topic",
"Legacy Octopush-DM": "舊版 Octopush-DM",
"Octopush API Version": "Octopush API 版本",
"From Name/Number": "發送人名稱/號碼",
"Recipient Number": "收件人號碼",
"smseaglePriority": "訊息優先度 (0-9預設 = 0)",
"smseagleEncoding": "以 Unicode 傳送",
"smseagleUrl": "您的 SMSEagle 裝置 URL",
"smseagleToken": "API 存取 Token",
"smseagleRecipient": "收件者 (以逗號分隔)",
"smseagleRecipientType": "收件者類型",
"smseagleContact": "聯絡人名稱",
"smseagleGroup": "群組名稱",
"smseagleTo": "電話號碼",
"smseagle": "SMSEagle",
"auto resolve": "自動解決",
"do nothing": "不進行任何操作",
"Auto resolve or acknowledged": "自動解決或標記已讀",
"Integration URL": "Integration URL",
"Integration Key": "Integration Key",
"wayToGetClickSendSMSToken": "您可以到 {0} 取得 API 使用者名稱和 API Key。",
"PushDeer Key": "PushDeer Key",
"onebotSafetyTips": "為了安全起見,必須設置存取 Token",
"onebotUserOrGroupId": "群組/使用者 ID",
"onebotPrivateMessage": "私人"
}

@ -89,7 +89,7 @@
"Heartbeat Interval": "心跳間隔",
"Retries": "重試次數",
"Heartbeat Retry Interval": "心跳重試間隔",
"Resend Notification if Down X times consequently": "若 X 次心跳皆離線,重新傳送通知",
"Resend Notification if Down X times consecutively": "若 X 次心跳皆離線,重新傳送通知",
"Advanced": "進階",
"Upside Down Mode": "顛倒模式",
"Max. Redirects": "最大重新導向次數",

@ -35,7 +35,8 @@ export default {
allowLoginDialog: false, // Allowed to show login dialog, but "loggedIn" have to be true too. This exists because prevent the login dialog show 0.1s in first before the socket server auth-ed.
loggedIn: false,
monitorList: { },
maintenanceList: { },
maintenanceList: {},
apiKeyList: {},
heartbeatList: { },
importantHeartbeatList: { },
avgPingList: { },
@ -135,6 +136,10 @@ export default {
this.maintenanceList = data;
});
socket.on("apiKeyList", (data) => {
this.apiKeyList = data;
});
socket.on("notificationList", (data) => {
this.notificationList = data;
});
@ -466,6 +471,17 @@ export default {
socket.emit("getMaintenanceList", callback);
},
/**
* Send list of API keys
* @param {socketCB} callback
*/
getAPIKeyList(callback) {
if (!callback) {
callback = () => { };
}
socket.emit("getAPIKeyList", callback);
},
/**
* Add a monitor
* @param {Object} monitor Object representing monitor to add
@ -540,6 +556,24 @@ export default {
socket.emit("deleteMaintenance", maintenanceID, callback);
},
/**
* Add an API key
* @param {Object} key API key to add
* @param {socketCB} callback
*/
addAPIKey(key, callback) {
socket.emit("addAPIKey", key, callback);
},
/**
* Delete specified API key
* @param {int} keyID ID of key to delete
* @param {socketCB} callback
*/
deleteAPIKey(keyID, callback) {
socket.emit("deleteAPIKey", keyID, callback);
},
/** Clear the hearbeat list */
clearData() {
console.log("reset heartbeat list");

@ -2,6 +2,7 @@
<transition name="slide-fade" appear>
<div v-if="monitor">
<h1> {{ monitor.name }}</h1>
<p v-if="monitor.description">{{ monitor.description }}</p>
<div class="tags">
<Tag v-for="tag in monitor.tags" :key="tag.id" :item="tag" :size="'sm'" />
</div>
@ -30,6 +31,9 @@
<router-link :to=" '/edit/' + monitor.id " class="btn btn-normal">
<font-awesome-icon icon="edit" /> {{ $t("Edit") }}
</router-link>
<router-link :to=" '/clone/' + monitor.id " class="btn btn-normal">
<font-awesome-icon icon="clone" /> {{ $t("Clone") }}
</router-link>
<button class="btn btn-danger" @click="deleteDialog">
<font-awesome-icon icon="trash" /> {{ $t("Delete") }}
</button>

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save