mirror of
https://github.com/librespeed/speedtest.git
synced 2026-10-21 07:40:50 +00:00
Add Swedish interface localization
This commit is contained in:
parent
aa84692df3
commit
bf1deac58b
9 changed files with 408 additions and 165 deletions
|
|
@ -64,6 +64,14 @@ A command line client is available [here](https://github.com/librespeed/speedtes
|
|||
|
||||
A .NET client library is available in the [`LibreSpeed.NET`](https://github.com/Memphizzz/LibreSpeed.NET) repo ([NuGet](https://www.nuget.org/packages/LibreSpeed.NET)), maintained by [MemphiZ](https://github.com/Memphizzz).
|
||||
|
||||
## Localization
|
||||
|
||||
The user interfaces load translations from `frontend/locales/`. English is the
|
||||
fallback; a supported browser language is selected automatically, or pass
|
||||
`?lang=sv` to select Swedish explicitly. Add a complete JSON catalog using the
|
||||
keys in `frontend/locales/en.json`; keep dynamic UI strings behind
|
||||
`LibreSpeedI18n.t()`.
|
||||
|
||||
## Development
|
||||
|
||||
If you want to contribute or develop with LibreSpeed, see [DEVELOPMENT.md](DEVELOPMENT.md) for information about using npm for development tasks, linting, and formatting.
|
||||
|
|
|
|||
|
|
@ -8,13 +8,14 @@
|
|||
/>
|
||||
<meta
|
||||
name="description"
|
||||
content="Free and Open Source Speedtest. Run it right now in your browser, or self-host on a PHP, Golang, Rust or Node server. License: LGPL."
|
||||
content="Free and Open Source Speedtest. Run it right now in your browser, or self-host on a PHP, Golang, Rust or Node server. License: LGPL." data-i18n-attr="content:page.description"
|
||||
/>
|
||||
<link rel="shortcut icon" href="images/favicon.svg" />
|
||||
<script type="text/javascript" src="speedtest.js"></script>
|
||||
<script type="text/javascript" src="javascript/index.js"></script>
|
||||
<script defer type="text/javascript" src="javascript/i18n.js"></script>
|
||||
<script defer type="text/javascript" src="javascript/index.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="styling/index.css" />
|
||||
<title>LibreSpeed - Free and Open Source Speedtest</title>
|
||||
<title data-i18n="page.title">LibreSpeed - Free and Open Source Speedtest</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
|
@ -22,30 +23,30 @@
|
|||
<img src="images/logo.svg" alt="LibreSpeed" />
|
||||
</header>
|
||||
<main>
|
||||
<h1>Free and Open Source Speedtest.</h1>
|
||||
<p class="tagline">No Flash, No Java, No Websockets, No Bullsh*t</p>
|
||||
<h1 data-i18n="heading">Free and Open Source Speedtest.</h1>
|
||||
<p class="tagline" data-i18n="tagline">No Flash, No Java, No Websockets, No Bullsh*t</p>
|
||||
|
||||
<div class="server-selector">
|
||||
<div class="chosen">
|
||||
<div class="chevron">
|
||||
<img src="images/chevron.svg" alt="select..." />
|
||||
</div>
|
||||
<p>current server</p>
|
||||
<h2 id="selected-server">searching nearest server...</h2>
|
||||
<p data-i18n="server.current">current server</p>
|
||||
<h2 id="selected-server" data-i18n="server.searching">searching nearest server...</h2>
|
||||
</div>
|
||||
<ul class="servers"></ul>
|
||||
<p class="sponsor" id="sponsor"> </p>
|
||||
</div>
|
||||
|
||||
<p id="privacy-warning" class="hidden">
|
||||
by clicking the start button you agree to our privacy policy<br />
|
||||
<a href="#" id="choose-privacy">or choose your privacy options</a>
|
||||
<span data-i18n="privacy.warning">by clicking the start button you agree to our privacy policy</span><br />
|
||||
<a href="#" id="choose-privacy"><span data-i18n="privacy.choose">or choose your privacy options</span></a>
|
||||
</p>
|
||||
<button class="disabled" id="start-button"></button>
|
||||
|
||||
<div class="gauge-layout">
|
||||
<div class="ping hidden">
|
||||
<span class="label">Ping</span>:
|
||||
<span class="label" data-i18n="metric.ping">Ping</span>:
|
||||
<span class="value" id="ping">00</span>ms
|
||||
</div>
|
||||
|
||||
|
|
@ -53,100 +54,96 @@
|
|||
<div class="progress"></div>
|
||||
<div class="speed"></div>
|
||||
<h1><span id="download-speed">00</span> Mbps</h1>
|
||||
<h2>Download</h2>
|
||||
<h2 data-i18n="metric.download">Download</h2>
|
||||
</div>
|
||||
|
||||
<div class="gauge upload" id="upload-gauge">
|
||||
<div class="progress"></div>
|
||||
<div class="speed"></div>
|
||||
<h1><span id="upload-speed">00</span> Mbps</h1>
|
||||
<h2>Upload</h2>
|
||||
<h2 data-i18n="metric.upload">Upload</h2>
|
||||
</div>
|
||||
|
||||
<div class="jitter hidden">
|
||||
<span class="label">Jitter</span>:
|
||||
<span class="label" data-i18n="metric.jitter">Jitter</span>:
|
||||
<span class="value" id="jitter">00</span>ms
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button class="small inverted hidden" id="share-results">
|
||||
Share results
|
||||
<span data-i18n="share.results">Share results</span>
|
||||
</button>
|
||||
</main>
|
||||
<footer>
|
||||
<p class="source">
|
||||
<a href="stability.html">stability test</a> |
|
||||
<a href="https://github.com/librespeed/speedtest">source code</a>
|
||||
<a href="stability.html" data-i18n="footer.stability">stability test</a> |
|
||||
<a href="https://github.com/librespeed/speedtest"> <span data-i18n="footer.source">source code</span></a>
|
||||
</p>
|
||||
</footer>
|
||||
|
||||
<dialog id="share">
|
||||
<div class="close-dialog">
|
||||
<img src="images/close-button.svg" alt="Close" />
|
||||
<img src="images/close-button.svg" alt="Close" data-i18n-attr="alt:dialog.close" />
|
||||
</div>
|
||||
<img id="results" src="" alt="Test results in graphical form" />
|
||||
<button id="copy-link">Copy link</button>
|
||||
<img id="results" src="" alt="Test results in graphical form" data-i18n-attr="alt:dialog.results-alt" />
|
||||
<button id="copy-link"><span data-i18n="share.copy">Copy link</span></button>
|
||||
</dialog>
|
||||
|
||||
<dialog id="privacy">
|
||||
<div class="close-dialog">
|
||||
<img src="images/close-button.svg" alt="Close" />
|
||||
<img src="images/close-button.svg" alt="Close" data-i18n-attr="alt:dialog.close" />
|
||||
</div>
|
||||
<section>
|
||||
<h1>Privacy Policy</h1>
|
||||
<h1 data-i18n="privacy.title">Privacy Policy</h1>
|
||||
<p>
|
||||
This HTML5 speed test server is configured with telemetry enabled.
|
||||
<span data-i18n="privacy.telemetry">This HTML5 speed test server is configured with telemetry enabled.</span>
|
||||
</p>
|
||||
|
||||
<h2>What data we collect</h2>
|
||||
<h2 data-i18n="privacy.collect-title">What data we collect</h2>
|
||||
<p>
|
||||
At the end of the test, the following data is collected and stored:
|
||||
<span data-i18n="privacy.collect-intro">At the end of the test, the following data is collected and stored:</span>
|
||||
</p>
|
||||
|
||||
<ul>
|
||||
<li>Test ID</li>
|
||||
<li>Time of testing</li>
|
||||
<li>Test results (download and upload speed, ping and jitter)</li>
|
||||
<li>IP address</li>
|
||||
<li>ISP information</li>
|
||||
<li>Approximate location (inferred from IP address, not GPS)</li>
|
||||
<li>User agent and browser locale</li>
|
||||
<li>Test log (contains no personal information)</li>
|
||||
<li data-i18n="privacy.item.test-id">Test ID</li>
|
||||
<li data-i18n="privacy.item.time">Time of testing</li>
|
||||
<li data-i18n="privacy.item.results">Test results (download and upload speed, ping and jitter)</li>
|
||||
<li data-i18n="privacy.item.ip">IP address</li>
|
||||
<li data-i18n="privacy.item.isp">ISP information</li>
|
||||
<li data-i18n="privacy.item.location">Approximate location (inferred from IP address, not GPS)</li>
|
||||
<li data-i18n="privacy.item.locale">User agent and browser locale</li>
|
||||
<li data-i18n="privacy.item.log">Test log (contains no personal information)</li>
|
||||
</ul>
|
||||
|
||||
<h2>How we use the data</h2>
|
||||
<p>Data collected through this service is used to:</p>
|
||||
<h2 data-i18n="privacy.use-title">How we use the data</h2>
|
||||
<p data-i18n="privacy.use-intro">Data collected through this service is used to:</p>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
Allow sharing of test results (sharable image for forums, etc.)
|
||||
<span data-i18n="privacy.use.share">Allow sharing of test results (sharable image for forums, etc.)</span>
|
||||
</li>
|
||||
<li>
|
||||
To improve the service offered to you (for instance, to detect
|
||||
problems on our side)
|
||||
<span data-i18n="privacy.use.improve">To improve the service offered to you (for instance, to detect problems on our side)</span>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<p>No personal information is disclosed to third parties.</p>
|
||||
<p data-i18n="privacy.no-disclosure">No personal information is disclosed to third parties.</p>
|
||||
|
||||
<h2>Your consent</h2>
|
||||
<h2 data-i18n="privacy.consent-title">Your consent</h2>
|
||||
<p>
|
||||
By starting the test, you consent to the terms of this privacy policy.
|
||||
<span data-i18n="privacy.consent">By starting the test, you consent to the terms of this privacy policy.</span>
|
||||
</p>
|
||||
|
||||
<h2>Data removal</h2>
|
||||
<h2 data-i18n="privacy.removal-title">Data removal</h2>
|
||||
<p>
|
||||
If you want to have your information deleted, you need to provide
|
||||
either the ID of the test or your IP address. This is the only way to
|
||||
identify your data, without this information we won't be able to
|
||||
comply with your request.
|
||||
<span data-i18n="privacy.removal">If you want to have your information deleted, you need to provide either the ID of the test or your IP address. This is the only way to identify your data, without this information we won't be able to comply with your request.</span>
|
||||
</p>
|
||||
<p>
|
||||
Contact this email address for all deletion requests:
|
||||
<span data-i18n="privacy.contact">Contact this email address for all deletion requests:</span>
|
||||
<a href="mailto:PUT@YOUR_EMAIL.HERE">TO BE FILLED BY DEVELOPER</a>.
|
||||
</p>
|
||||
</section>
|
||||
<button id="close-privacy">Close</button>
|
||||
<button id="close-privacy"><span data-i18n="dialog.close">Close</span></button>
|
||||
</dialog>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||
56
frontend/javascript/i18n.js
Normal file
56
frontend/javascript/i18n.js
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
(() => {
|
||||
const DEFAULT_LANGUAGE = "en";
|
||||
const SUPPORTED_LANGUAGES = new Set(["en", "sv"]);
|
||||
const script = document.currentScript;
|
||||
const localesURL = new URL("../locales/", script.src);
|
||||
let messages = {};
|
||||
|
||||
function languageFromRequest() {
|
||||
const requested = new URLSearchParams(window.location.search).get("lang");
|
||||
if (requested) return requested.toLowerCase().split("-")[0];
|
||||
return (navigator.languages || [navigator.language || DEFAULT_LANGUAGE])
|
||||
.map((language) => language.toLowerCase().split("-")[0])
|
||||
.find((language) => SUPPORTED_LANGUAGES.has(language)) || DEFAULT_LANGUAGE;
|
||||
}
|
||||
|
||||
function interpolate(value, parameters) {
|
||||
return value.replace(/\{(\w+)\}/g, (match, key) =>
|
||||
Object.prototype.hasOwnProperty.call(parameters, key) ? parameters[key] : match
|
||||
);
|
||||
}
|
||||
|
||||
function translate(key, fallback = key, parameters = {}) {
|
||||
return interpolate(messages[key] || fallback, parameters);
|
||||
}
|
||||
|
||||
function translateDocument() {
|
||||
document.querySelectorAll("[data-i18n]").forEach((element) => {
|
||||
const key = element.dataset.i18n;
|
||||
element.textContent = translate(key, element.textContent.trim());
|
||||
});
|
||||
document.querySelectorAll("[data-i18n-attr]").forEach((element) => {
|
||||
element.dataset.i18nAttr.split(",").forEach((binding) => {
|
||||
const [attribute, key] = binding.split(":");
|
||||
if (attribute && key) element.setAttribute(attribute, translate(key, element.getAttribute(attribute) || key));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
const language = languageFromRequest();
|
||||
const ready = fetch(new URL(`${language}.json`, localesURL))
|
||||
.then((response) => {
|
||||
if (!response.ok) throw new Error(`Unable to load ${language} translations`);
|
||||
return response.json();
|
||||
})
|
||||
.then((catalog) => {
|
||||
messages = catalog;
|
||||
document.documentElement.lang = language;
|
||||
translateDocument();
|
||||
})
|
||||
.catch((error) => {
|
||||
console.warn("LibreSpeed localization unavailable:", error);
|
||||
document.documentElement.lang = DEFAULT_LANGUAGE;
|
||||
});
|
||||
|
||||
window.LibreSpeedI18n = { language, ready, t: translate };
|
||||
})();
|
||||
|
|
@ -26,6 +26,7 @@ const testState = {
|
|||
|
||||
// Bootstrap the application when the DOM is ready
|
||||
window.addEventListener("DOMContentLoaded", async () => {
|
||||
await window.LibreSpeedI18n.ready;
|
||||
createSpeedtest();
|
||||
hookUpButtons();
|
||||
startRenderingLoop();
|
||||
|
|
@ -127,10 +128,10 @@ async function copyLinkButtonClickHandler() {
|
|||
await navigator.clipboard.writeText(link);
|
||||
const button = document.querySelector("#copy-link");
|
||||
button.classList.add("active");
|
||||
button.textContent = "Copied!";
|
||||
button.textContent = window.LibreSpeedI18n.t("share.copied", "Copied!");
|
||||
setTimeout(() => {
|
||||
button.classList.remove("active");
|
||||
button.textContent = "Copy link";
|
||||
button.textContent = window.LibreSpeedI18n.t("share.copy", "Copy link");
|
||||
}, 3000);
|
||||
}
|
||||
|
||||
|
|
@ -212,7 +213,7 @@ async function applyServerListJSON() {
|
|||
selectServer(bestServer);
|
||||
} else {
|
||||
alert(
|
||||
"Can't reach any of the speedtest servers! But you're on this page. Something weird is going on with your network."
|
||||
window.LibreSpeedI18n.t("error.no-servers", "Can't reach any of the speedtest servers! But you're on this page. Something weird is going on with your network.")
|
||||
);
|
||||
}
|
||||
});
|
||||
|
|
@ -334,10 +335,10 @@ function startRenderingLoop() {
|
|||
const resultsImage = document.querySelector("#results");
|
||||
|
||||
const buttonTexts = {
|
||||
[INITIALIZING]: "Loading...",
|
||||
[READY]: "Let's start",
|
||||
[RUNNING]: "Abort",
|
||||
[FINISHED]: "Restart",
|
||||
[INITIALIZING]: window.LibreSpeedI18n.t("button.loading", "Loading..."),
|
||||
[READY]: window.LibreSpeedI18n.t("button.start", "Let's start"),
|
||||
[RUNNING]: window.LibreSpeedI18n.t("button.abort", "Abort"),
|
||||
[FINISHED]: window.LibreSpeedI18n.t("button.restart", "Restart"),
|
||||
};
|
||||
|
||||
// Show copy link button only if navigator.clipboard is available
|
||||
|
|
@ -358,9 +359,9 @@ function startRenderingLoop() {
|
|||
selectedServer.textContent = server.name;
|
||||
if (server.sponsorName) {
|
||||
if (server.sponsorURL) {
|
||||
sponsor.innerHTML = `Sponsor: <a href="${server.sponsorURL}">${server.sponsorName}</a>`;
|
||||
sponsor.innerHTML = `${window.LibreSpeedI18n.t("server.sponsor", "Sponsor: {name}", { name: "" })}<a href="${server.sponsorURL}">${server.sponsorName}</a>`;
|
||||
} else {
|
||||
sponsor.textContent = `Sponsor: ${server.sponsorName}`;
|
||||
sponsor.textContent = window.LibreSpeedI18n.t("server.sponsor", "Sponsor: {name}", { name: server.sponsorName });
|
||||
}
|
||||
} else {
|
||||
sponsor.innerHTML = " ";
|
||||
|
|
@ -442,7 +443,7 @@ function startRenderingLoop() {
|
|||
privacyWarning.innerHTML = '';
|
||||
|
||||
const connectedThrough = document.createElement('span');
|
||||
connectedThrough.textContent = 'You are connected through:';
|
||||
connectedThrough.textContent = window.LibreSpeedI18n.t("connection.through", "You are connected through:");
|
||||
|
||||
const ipAddress = document.createTextNode(testState.testData.clientIp);
|
||||
|
||||
|
|
|
|||
91
frontend/locales/en.json
Normal file
91
frontend/locales/en.json
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
{
|
||||
"page.title": "LibreSpeed - Free and Open Source Speedtest",
|
||||
"page.description": "Free and Open Source Speedtest. Run it right now in your browser, or self-host on a PHP, Golang, Rust or Node server. License: LGPL.",
|
||||
"heading": "Free and Open Source Speedtest.",
|
||||
"tagline": "No Flash, No Java, No Websockets, No Bullsh*t",
|
||||
"server.current": "current server",
|
||||
"server.searching": "searching nearest server...",
|
||||
"privacy.warning": "by clicking the start button you agree to our privacy policy",
|
||||
"privacy.choose": "or choose your privacy options",
|
||||
"metric.download": "Download",
|
||||
"metric.upload": "Upload",
|
||||
"metric.ping": "Ping",
|
||||
"metric.jitter": "Jitter",
|
||||
"share.results": "Share results",
|
||||
"footer.stability": "stability test",
|
||||
"footer.source": "source code",
|
||||
"dialog.close": "Close",
|
||||
"dialog.results-alt": "Test results in graphical form",
|
||||
"share.copy": "Copy link",
|
||||
"share.copied": "Copied!",
|
||||
"privacy.title": "Privacy Policy",
|
||||
"privacy.telemetry": "This HTML5 speed test server is configured with telemetry enabled.",
|
||||
"privacy.collect-title": "What data we collect",
|
||||
"privacy.collect-intro": "At the end of the test, the following data is collected and stored:",
|
||||
"privacy.item.test-id": "Test ID",
|
||||
"privacy.item.time": "Time of testing",
|
||||
"privacy.item.results": "Test results (download and upload speed, ping and jitter)",
|
||||
"privacy.item.ip": "IP address",
|
||||
"privacy.item.isp": "ISP information",
|
||||
"privacy.item.location": "Approximate location (inferred from IP address, not GPS)",
|
||||
"privacy.item.locale": "User agent and browser locale",
|
||||
"privacy.item.log": "Test log (contains no personal information)",
|
||||
"privacy.use-title": "How we use the data",
|
||||
"privacy.use-intro": "Data collected through this service is used to:",
|
||||
"privacy.use.share": "Allow sharing of test results (sharable image for forums, etc.)",
|
||||
"privacy.use.improve": "To improve the service offered to you (for instance, to detect problems on our side)",
|
||||
"privacy.no-disclosure": "No personal information is disclosed to third parties.",
|
||||
"privacy.consent-title": "Your consent",
|
||||
"privacy.consent": "By starting the test, you consent to the terms of this privacy policy.",
|
||||
"privacy.removal-title": "Data removal",
|
||||
"privacy.removal": "If you want to have your information deleted, you need to provide either the ID of the test or your IP address. This is the only way to identify your data, without this information we won't be able to comply with your request.",
|
||||
"privacy.contact": "Contact this email address for all deletion requests:",
|
||||
"button.loading": "Loading...",
|
||||
"button.start": "Let's start",
|
||||
"button.abort": "Abort",
|
||||
"button.restart": "Restart",
|
||||
"server.sponsor": "Sponsor: {name}",
|
||||
"connection.through": "You are connected through:",
|
||||
"error.no-servers": "Can't reach any of the speedtest servers! But you're on this page. Something weird is going on with your network.",
|
||||
"classic.selecting": "Selecting a server...",
|
||||
"classic.no-servers": "No servers available",
|
||||
"classic.privacy": "Privacy",
|
||||
"classic.server": "Server:",
|
||||
"classic.share": "Share results",
|
||||
"classic.test-id": "Test ID:",
|
||||
"classic.modern": "Try the modern design",
|
||||
"classic.stability": "Stability Test",
|
||||
"classic.source": "Source code",
|
||||
"classic.link-copied": "Link copied",
|
||||
"classic.start": "Start",
|
||||
"classic.abort": "Abort",
|
||||
"stability.title": "LibreSpeed - Stability Test",
|
||||
"stability.back": "Speed Test",
|
||||
"stability.seconds": "{count} Seconds",
|
||||
"stability.minutes": "{count} Minutes",
|
||||
"stability.local": "Local Server",
|
||||
"stability.finding": "Finding...",
|
||||
"stability.reset": "Reset",
|
||||
"stability.server": "Server:",
|
||||
"stability.current": "Current",
|
||||
"stability.average": "Average",
|
||||
"stability.min": "Min",
|
||||
"stability.max": "Max",
|
||||
"stability.failed": "Failed Requests",
|
||||
"stability.elapsed": "Elapsed",
|
||||
"stability.alert": "Alert threshold:",
|
||||
"stability.off": "Off",
|
||||
"stability.download-csv": "Download CSV",
|
||||
"stability.source": "Source code",
|
||||
"stability.60-seconds": "60 Seconds",
|
||||
"stability.90-seconds": "90 Seconds",
|
||||
"stability.2-minutes": "2 Minutes",
|
||||
"stability.3-minutes": "3 Minutes",
|
||||
"stability.5-minutes": "5 Minutes",
|
||||
"stability.finding-server": "Finding best server...",
|
||||
"stability.no-server": "No reachable local server found",
|
||||
"stability.great": "Great",
|
||||
"stability.good": "Good",
|
||||
"stability.poor": "Poor",
|
||||
"stability.bad": "Bad"
|
||||
}
|
||||
91
frontend/locales/sv.json
Normal file
91
frontend/locales/sv.json
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
{
|
||||
"page.title": "LibreSpeed – fritt hastighetstest med öppen källkod",
|
||||
"page.description": "Fritt hastighetstest med öppen källkod. Kör det direkt i webbläsaren eller driftssätt det själv på en PHP-, Go-, Rust- eller Node-server. Licens: LGPL.",
|
||||
"heading": "Fritt hastighetstest med öppen källkod.",
|
||||
"tagline": "Ingen Flash, ingen Java, inga WebSockets, inget struntprat",
|
||||
"server.current": "aktuell server",
|
||||
"server.searching": "söker efter närmaste server...",
|
||||
"privacy.warning": "genom att klicka på startknappen godkänner du vår integritetspolicy",
|
||||
"privacy.choose": "eller välj dina integritetsalternativ",
|
||||
"metric.download": "Hämtning",
|
||||
"metric.upload": "Sändning",
|
||||
"metric.ping": "Ping",
|
||||
"metric.jitter": "Jitter",
|
||||
"share.results": "Dela resultat",
|
||||
"footer.stability": "stabilitetstest",
|
||||
"footer.source": "källkod",
|
||||
"dialog.close": "Stäng",
|
||||
"dialog.results-alt": "Testresultat i grafisk form",
|
||||
"share.copy": "Kopiera länk",
|
||||
"share.copied": "Kopierad!",
|
||||
"privacy.title": "Integritetspolicy",
|
||||
"privacy.telemetry": "Den här HTML5-hastighetstestservern är konfigurerad med telemetri aktiverad.",
|
||||
"privacy.collect-title": "Vilka data vi samlar in",
|
||||
"privacy.collect-intro": "När testet är klart samlas följande data in och lagras:",
|
||||
"privacy.item.test-id": "Test-id",
|
||||
"privacy.item.time": "Tidpunkt för testet",
|
||||
"privacy.item.results": "Testresultat (hämtnings- och sändningshastighet, ping och jitter)",
|
||||
"privacy.item.ip": "IP-adress",
|
||||
"privacy.item.isp": "Information om internetleverantör",
|
||||
"privacy.item.location": "Ungefärlig plats (härledd från IP-adress, inte GPS)",
|
||||
"privacy.item.locale": "Webbläsaragent och språkinställning",
|
||||
"privacy.item.log": "Testlogg (innehåller inga personuppgifter)",
|
||||
"privacy.use-title": "Så använder vi data",
|
||||
"privacy.use-intro": "Data som samlas in via tjänsten används för att:",
|
||||
"privacy.use.share": "möjliggöra delning av testresultat (delbar bild för forum med mera)",
|
||||
"privacy.use.improve": "förbättra tjänsten vi erbjuder dig (till exempel för att upptäcka problem hos oss)",
|
||||
"privacy.no-disclosure": "Inga personuppgifter lämnas ut till tredje part.",
|
||||
"privacy.consent-title": "Ditt samtycke",
|
||||
"privacy.consent": "Genom att starta testet samtycker du till villkoren i den här integritetspolicyn.",
|
||||
"privacy.removal-title": "Radering av data",
|
||||
"privacy.removal": "Om du vill få dina uppgifter raderade behöver du ange antingen testets id eller din IP-adress. Det är det enda sättet att identifiera dina uppgifter; utan den informationen kan vi inte uppfylla din begäran.",
|
||||
"privacy.contact": "Kontakta den här e-postadressen för alla begäranden om radering:",
|
||||
"button.loading": "Läser in...",
|
||||
"button.start": "Starta testet",
|
||||
"button.abort": "Avbryt",
|
||||
"button.restart": "Starta om",
|
||||
"server.sponsor": "Sponsor: {name}",
|
||||
"connection.through": "Du är ansluten via:",
|
||||
"error.no-servers": "Det går inte att nå någon av hastighetstestservrarna. Du är ändå på den här sidan, så något verkar vara fel med nätverket.",
|
||||
"classic.selecting": "Väljer server...",
|
||||
"classic.no-servers": "Inga servrar är tillgängliga",
|
||||
"classic.privacy": "Integritet",
|
||||
"classic.server": "Server:",
|
||||
"classic.share": "Dela resultat",
|
||||
"classic.test-id": "Test-id:",
|
||||
"classic.modern": "Prova den moderna designen",
|
||||
"classic.stability": "Stabilitetstest",
|
||||
"classic.source": "Källkod",
|
||||
"classic.link-copied": "Länken har kopierats",
|
||||
"classic.start": "Starta",
|
||||
"classic.abort": "Avbryt",
|
||||
"stability.title": "LibreSpeed – stabilitetstest",
|
||||
"stability.back": "Hastighetstest",
|
||||
"stability.seconds": "{count} sekunder",
|
||||
"stability.minutes": "{count} minuter",
|
||||
"stability.local": "Lokal server",
|
||||
"stability.finding": "Söker...",
|
||||
"stability.reset": "Återställ",
|
||||
"stability.server": "Server:",
|
||||
"stability.current": "Aktuell",
|
||||
"stability.average": "Genomsnitt",
|
||||
"stability.min": "Min",
|
||||
"stability.max": "Max",
|
||||
"stability.failed": "Misslyckade begäranden",
|
||||
"stability.elapsed": "Förfluten tid",
|
||||
"stability.alert": "Larmgräns:",
|
||||
"stability.off": "Av",
|
||||
"stability.download-csv": "Hämta CSV",
|
||||
"stability.source": "Källkod",
|
||||
"stability.60-seconds": "60 sekunder",
|
||||
"stability.90-seconds": "90 sekunder",
|
||||
"stability.2-minutes": "2 minuter",
|
||||
"stability.3-minutes": "3 minuter",
|
||||
"stability.5-minutes": "5 minuter",
|
||||
"stability.finding-server": "Söker bästa servern...",
|
||||
"stability.no-server": "Ingen lokal server som kan nås hittades",
|
||||
"stability.great": "Utmärkt",
|
||||
"stability.good": "Bra",
|
||||
"stability.poor": "Svag",
|
||||
"stability.bad": "Dålig"
|
||||
}
|
||||
|
|
@ -47,7 +47,7 @@
|
|||
initUI();
|
||||
} else { //multiple servers
|
||||
var noServersAvailable = function () {
|
||||
I("message").innerHTML = "No servers available";
|
||||
I("message").textContent = window.LibreSpeedI18n.t("classic.no-servers", "No servers available");
|
||||
}
|
||||
var runServerSelect = function () {
|
||||
s.selectServer(function (server) {
|
||||
|
|
@ -309,11 +309,11 @@
|
|||
}
|
||||
|
||||
#startStopBtn:before {
|
||||
content: "Start";
|
||||
content: attr(data-label-start);
|
||||
}
|
||||
|
||||
#startStopBtn.running:before {
|
||||
content: "Abort";
|
||||
content: attr(data-label-abort);
|
||||
}
|
||||
|
||||
#serverArea {
|
||||
|
|
@ -520,39 +520,39 @@
|
|||
<title>LibreSpeed</title>
|
||||
</head>
|
||||
|
||||
<body onload="initServers()">
|
||||
<body onload="window.LibreSpeedI18n.ready.then(initServers)">
|
||||
<h1>LibreSpeed</h1>
|
||||
<div id="loading" class="visible">
|
||||
<p id="message"><span class="loadCircle"></span>Selecting a server...</p>
|
||||
<p id="message"><span class="loadCircle"></span><span data-i18n="classic.selecting">Selecting a server...</span></p>
|
||||
</div>
|
||||
<div id="testWrapper" class="hidden">
|
||||
<button id="startStopBtn" onclick="startStop()" aria-label="Start"></button><br />
|
||||
<a class="privacy" href="#" onclick="I('privacyPolicy').style.display=''">Privacy</a>
|
||||
<button id="startStopBtn" onclick="startStop()" aria-label="Start" data-label-start="Start" data-label-abort="Abort" data-i18n-attr="aria-label:classic.start,data-label-start:classic.start,data-label-abort:classic.abort"></button><br />
|
||||
<a class="privacy" href="#" onclick="I('privacyPolicy').style.display=''" data-i18n="classic.privacy">Privacy</a>
|
||||
<div id="serverArea">
|
||||
Server: <select id="server" onchange="s.setSelectedServer(SPEEDTEST_SERVERS[this.value])"></select>
|
||||
</div>
|
||||
<div id="test">
|
||||
<div class="testGroup">
|
||||
<div class="testArea2">
|
||||
<div class="testName">Ping</div>
|
||||
<div class="testName" data-i18n="metric.ping">Ping</div>
|
||||
<div id="pingText" class="meterText" style="color:#AA6060"></div>
|
||||
<div class="unit">ms</div>
|
||||
</div>
|
||||
<div class="testArea2">
|
||||
<div class="testName">Jitter</div>
|
||||
<div class="testName" data-i18n="metric.jitter">Jitter</div>
|
||||
<div id="jitText" class="meterText" style="color:#AA6060"></div>
|
||||
<div class="unit">ms</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="testGroup">
|
||||
<div class="testArea">
|
||||
<div class="testName">Download</div>
|
||||
<div class="testName" data-i18n="metric.download">Download</div>
|
||||
<canvas id="dlMeter" class="meter"></canvas>
|
||||
<div id="dlText" class="meterText"></div>
|
||||
<div class="unit">Mbit/s</div>
|
||||
</div>
|
||||
<div class="testArea">
|
||||
<div class="testName">Upload</div>
|
||||
<div class="testName" data-i18n="metric.upload">Upload</div>
|
||||
<canvas id="ulMeter" class="meter"></canvas>
|
||||
<div id="ulText" class="meterText"></div>
|
||||
<div class="unit">Mbit/s</div>
|
||||
|
|
@ -562,34 +562,34 @@
|
|||
<span id="ip"></span>
|
||||
</div>
|
||||
<div id="shareArea" style="display:none">
|
||||
<h3>Share results</h3>
|
||||
<h3 data-i18n="classic.share">Share results</h3>
|
||||
<p>Test ID: <span id="testId"></span></p>
|
||||
<input type="text" value="" id="resultsURL" readonly="readonly"
|
||||
onclick="this.select();this.focus();this.select();document.execCommand('copy');alert('Link copied')" />
|
||||
onclick="this.select();this.focus();this.select();document.execCommand('copy');alert(window.LibreSpeedI18n.t('classic.link-copied', 'Link copied'))" />
|
||||
<img src="" id="resultsImg" />
|
||||
</div>
|
||||
</div>
|
||||
<a href="index.html?design=new">Try the modern design</a><br>
|
||||
<a href="stability.html">Stability Test</a> | <a href="https://github.com/librespeed/speedtest">Source code</a>
|
||||
<a href="index.html?design=new" data-i18n="classic.modern">Try the modern design</a><br>
|
||||
<a href="stability.html" data-i18n="classic.stability">Stability Test</a> | <a href="https://github.com/librespeed/speedtest" data-i18n="classic.source">Source code</a>
|
||||
</div>
|
||||
<div id="privacyPolicy" style="display:none">
|
||||
<h2>Privacy Policy</h2>
|
||||
<p>This HTML5 speed test server is configured with telemetry enabled.</p>
|
||||
<h4>What data we collect</h4>
|
||||
<h2 data-i18n="privacy.title">Privacy Policy</h2>
|
||||
<p data-i18n="privacy.telemetry">This HTML5 speed test server is configured with telemetry enabled.</p>
|
||||
<h4 data-i18n="privacy.collect-title">What data we collect</h4>
|
||||
<p>
|
||||
At the end of the test, the following data is collected and stored:
|
||||
<ul>
|
||||
<li>Test ID</li>
|
||||
<li>Time of testing</li>
|
||||
<li>Test results (download and upload speed, ping and jitter)</li>
|
||||
<li>IP address</li>
|
||||
<li>ISP information</li>
|
||||
<li>Approximate location (inferred from IP address, not GPS)</li>
|
||||
<li>User agent and browser locale</li>
|
||||
<li>Test log (contains no personal information)</li>
|
||||
<li data-i18n="privacy.item.test-id">Test ID</li>
|
||||
<li data-i18n="privacy.item.time">Time of testing</li>
|
||||
<li data-i18n="privacy.item.results">Test results (download and upload speed, ping and jitter)</li>
|
||||
<li data-i18n="privacy.item.ip">IP address</li>
|
||||
<li data-i18n="privacy.item.isp">ISP information</li>
|
||||
<li data-i18n="privacy.item.location">Approximate location (inferred from IP address, not GPS)</li>
|
||||
<li data-i18n="privacy.item.locale">User agent and browser locale</li>
|
||||
<li data-i18n="privacy.item.log">Test log (contains no personal information)</li>
|
||||
</ul>
|
||||
</p>
|
||||
<h4>How we use the data</h4>
|
||||
<h4 data-i18n="privacy.use-title">How we use the data</h4>
|
||||
<p>
|
||||
Data collected through this service is used to:
|
||||
<ul>
|
||||
|
|
@ -598,11 +598,11 @@
|
|||
</ul>
|
||||
No personal information is disclosed to third parties.
|
||||
</p>
|
||||
<h4>Your consent</h4>
|
||||
<h4 data-i18n="privacy.consent-title">Your consent</h4>
|
||||
<p>
|
||||
By starting the test, you consent to the terms of this privacy policy.
|
||||
</p>
|
||||
<h4>Data removal</h4>
|
||||
<h4 data-i18n="privacy.removal-title">Data removal</h4>
|
||||
<p>
|
||||
If you want to have your information deleted, you need to provide either the ID of the test or your IP
|
||||
address. This is the only way to identify your data, without this information we won't be able to comply
|
||||
|
|
@ -616,6 +616,7 @@
|
|||
</div>
|
||||
<br />
|
||||
</div>
|
||||
<script defer src="frontend/javascript/i18n.js"></script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
|
||||
<meta name="description"
|
||||
content="Free and Open Source Speedtest. Run it right now in your browser, or self-host on a PHP, Golang, Rust or Node server. License: LGPL." />
|
||||
content="Free and Open Source Speedtest. Run it right now in your browser, or self-host on a PHP, Golang, Rust or Node server. License: LGPL." data-i18n-attr="content:page.description" />
|
||||
<link rel="shortcut icon" href="frontend/images/favicon.svg" />
|
||||
<link rel="manifest" href="manifest.webmanifest" />
|
||||
<link rel="apple-touch-icon" href="images/icon-192.png" />
|
||||
|
|
@ -15,9 +15,10 @@
|
|||
// Set this to a different URL to load the server list from another location.
|
||||
var SPEEDTEST_SERVERS = "server-list.json";
|
||||
</script>
|
||||
<script type="text/javascript" src="frontend/javascript/index.js"></script>
|
||||
<script defer type="text/javascript" src="frontend/javascript/i18n.js"></script>
|
||||
<script defer type="text/javascript" src="frontend/javascript/index.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="frontend/styling/index.css" />
|
||||
<title>LibreSpeed - Free and Open Source Speedtest</title>
|
||||
<title data-i18n="page.title">LibreSpeed - Free and Open Source Speedtest</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
|
@ -25,30 +26,30 @@
|
|||
<img src="frontend/images/logo.svg" alt="LibreSpeed" />
|
||||
</header>
|
||||
<main>
|
||||
<h1>Free and Open Source Speedtest.</h1>
|
||||
<p class="tagline">No Flash, No Java, No Websockets, No Bullsh*t</p>
|
||||
<h1 data-i18n="heading">Free and Open Source Speedtest.</h1>
|
||||
<p class="tagline" data-i18n="tagline">No Flash, No Java, No Websockets, No Bullsh*t</p>
|
||||
|
||||
<div class="server-selector">
|
||||
<div class="chosen">
|
||||
<div class="chevron">
|
||||
<img src="frontend/images/chevron.svg" alt="select..." />
|
||||
</div>
|
||||
<p>current server</p>
|
||||
<h2 id="selected-server">searching nearest server...</h2>
|
||||
<p data-i18n="server.current">current server</p>
|
||||
<h2 id="selected-server" data-i18n="server.searching">searching nearest server...</h2>
|
||||
</div>
|
||||
<ul class="servers"></ul>
|
||||
<p class="sponsor" id="sponsor"> </p>
|
||||
</div>
|
||||
|
||||
<p id="privacy-warning" class="hidden">
|
||||
by clicking the start button you agree to our privacy policy<br />
|
||||
<a href="#" id="choose-privacy">or choose your privacy options</a>
|
||||
<span data-i18n="privacy.warning">by clicking the start button you agree to our privacy policy</span><br />
|
||||
<a href="#" id="choose-privacy"><span data-i18n="privacy.choose">or choose your privacy options</span></a>
|
||||
</p>
|
||||
<button class="disabled" id="start-button"></button>
|
||||
|
||||
<div class="gauge-layout">
|
||||
<div class="ping hidden">
|
||||
<span class="label">Ping</span>:
|
||||
<span class="label" data-i18n="metric.ping">Ping</span>:
|
||||
<span class="value" id="ping">00</span>ms
|
||||
</div>
|
||||
|
||||
|
|
@ -56,18 +57,18 @@
|
|||
<div class="progress"></div>
|
||||
<div class="speed"></div>
|
||||
<h1><span id="download-speed">00</span> Mbps</h1>
|
||||
<h2>Download</h2>
|
||||
<h2 data-i18n="metric.download">Download</h2>
|
||||
</div>
|
||||
|
||||
<div class="gauge upload" id="upload-gauge">
|
||||
<div class="progress"></div>
|
||||
<div class="speed"></div>
|
||||
<h1><span id="upload-speed">00</span> Mbps</h1>
|
||||
<h2>Upload</h2>
|
||||
<h2 data-i18n="metric.upload">Upload</h2>
|
||||
</div>
|
||||
|
||||
<div class="jitter hidden">
|
||||
<span class="label">Jitter</span>:
|
||||
<span class="label" data-i18n="metric.jitter">Jitter</span>:
|
||||
<span class="value" id="jitter">00</span>ms
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -78,77 +79,73 @@
|
|||
</main>
|
||||
<footer>
|
||||
<p class="source">
|
||||
<a href="stability.html">stability test</a> | <a href="https://github.com/librespeed/speedtest">source code</a>
|
||||
<a href="stability.html" data-i18n="footer.stability">stability test</a> | <a href="https://github.com/librespeed/speedtest"> <span data-i18n="footer.source">source code</span></a>
|
||||
</p>
|
||||
</footer>
|
||||
|
||||
<dialog id="share">
|
||||
<div class="close-dialog">
|
||||
<img src="frontend/images/close-button.svg" alt="Close" />
|
||||
<img src="frontend/images/close-button.svg" alt="Close" data-i18n-attr="alt:dialog.close" />
|
||||
</div>
|
||||
<img id="results" src="" alt="Test results in graphical form" />
|
||||
<button id="copy-link">Copy link</button>
|
||||
<img id="results" src="" alt="Test results in graphical form" data-i18n-attr="alt:dialog.results-alt" />
|
||||
<button id="copy-link"><span data-i18n="share.copy">Copy link</span></button>
|
||||
</dialog>
|
||||
|
||||
<dialog id="privacy">
|
||||
<div class="close-dialog">
|
||||
<img src="frontend/images/close-button.svg" alt="Close" />
|
||||
<img src="frontend/images/close-button.svg" alt="Close" data-i18n-attr="alt:dialog.close" />
|
||||
</div>
|
||||
<section>
|
||||
<h1>Privacy Policy</h1>
|
||||
<h1 data-i18n="privacy.title">Privacy Policy</h1>
|
||||
<p>
|
||||
This HTML5 speed test server is configured with telemetry enabled.
|
||||
<span data-i18n="privacy.telemetry">This HTML5 speed test server is configured with telemetry enabled.</span>
|
||||
</p>
|
||||
|
||||
<h2>What data we collect</h2>
|
||||
<h2 data-i18n="privacy.collect-title">What data we collect</h2>
|
||||
<p>
|
||||
At the end of the test, the following data is collected and stored:
|
||||
<span data-i18n="privacy.collect-intro">At the end of the test, the following data is collected and stored:</span>
|
||||
</p>
|
||||
|
||||
<ul>
|
||||
<li>Test ID</li>
|
||||
<li>Time of testing</li>
|
||||
<li>Test results (download and upload speed, ping and jitter)</li>
|
||||
<li>IP address</li>
|
||||
<li>ISP information</li>
|
||||
<li>Approximate location (inferred from IP address, not GPS)</li>
|
||||
<li>User agent and browser locale</li>
|
||||
<li>Test log (contains no personal information)</li>
|
||||
<li data-i18n="privacy.item.test-id">Test ID</li>
|
||||
<li data-i18n="privacy.item.time">Time of testing</li>
|
||||
<li data-i18n="privacy.item.results">Test results (download and upload speed, ping and jitter)</li>
|
||||
<li data-i18n="privacy.item.ip">IP address</li>
|
||||
<li data-i18n="privacy.item.isp">ISP information</li>
|
||||
<li data-i18n="privacy.item.location">Approximate location (inferred from IP address, not GPS)</li>
|
||||
<li data-i18n="privacy.item.locale">User agent and browser locale</li>
|
||||
<li data-i18n="privacy.item.log">Test log (contains no personal information)</li>
|
||||
</ul>
|
||||
|
||||
<h2>How we use the data</h2>
|
||||
<p>Data collected through this service is used to:</p>
|
||||
<h2 data-i18n="privacy.use-title">How we use the data</h2>
|
||||
<p data-i18n="privacy.use-intro">Data collected through this service is used to:</p>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
Allow sharing of test results (sharable image for forums, etc.)
|
||||
<span data-i18n="privacy.use.share">Allow sharing of test results (sharable image for forums, etc.)</span>
|
||||
</li>
|
||||
<li>
|
||||
To improve the service offered to you (for instance, to detect
|
||||
problems on our side)
|
||||
<span data-i18n="privacy.use.improve">To improve the service offered to you (for instance, to detect problems on our side)</span>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<p>No personal information is disclosed to third parties.</p>
|
||||
<p data-i18n="privacy.no-disclosure">No personal information is disclosed to third parties.</p>
|
||||
|
||||
<h2>Your consent</h2>
|
||||
<h2 data-i18n="privacy.consent-title">Your consent</h2>
|
||||
<p>
|
||||
By starting the test, you consent to the terms of this privacy policy.
|
||||
<span data-i18n="privacy.consent">By starting the test, you consent to the terms of this privacy policy.</span>
|
||||
</p>
|
||||
|
||||
<h2>Data removal</h2>
|
||||
<h2 data-i18n="privacy.removal-title">Data removal</h2>
|
||||
<p>
|
||||
If you want to have your information deleted, you need to provide
|
||||
either the ID of the test or your IP address. This is the only way to
|
||||
identify your data, without this information we won't be able to
|
||||
comply with your request.
|
||||
<span data-i18n="privacy.removal">If you want to have your information deleted, you need to provide either the ID of the test or your IP address. This is the only way to identify your data, without this information we won't be able to comply with your request.</span>
|
||||
</p>
|
||||
<p>
|
||||
Contact this email address for all deletion requests:
|
||||
<span data-i18n="privacy.contact">Contact this email address for all deletion requests:</span>
|
||||
<a href="mailto:PUT@YOUR_EMAIL.HERE">TO BE FILLED BY DEVELOPER</a>.
|
||||
</p>
|
||||
</section>
|
||||
<button id="close-privacy">Close</button>
|
||||
<button id="close-privacy"><span data-i18n="dialog.close">Close</span></button>
|
||||
</dialog>
|
||||
</body>
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
<link rel="shortcut icon" href="favicon.ico" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no, user-scalable=no" />
|
||||
<meta charset="UTF-8" />
|
||||
<title>LibreSpeed - Stability Test</title>
|
||||
<title data-i18n="stability.title">LibreSpeed - Stability Test</title>
|
||||
<style type="text/css">
|
||||
html,
|
||||
body {
|
||||
|
|
@ -75,10 +75,10 @@
|
|||
inset 0 0 0 rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
#startBtn:before {
|
||||
content: "Start";
|
||||
content: attr(data-label-start);
|
||||
}
|
||||
#startBtn.finding:before {
|
||||
content: "Finding...";
|
||||
content: attr(data-label-finding);
|
||||
}
|
||||
#startBtn.running {
|
||||
background-color: #ff3030;
|
||||
|
|
@ -88,7 +88,7 @@
|
|||
opacity: 1;
|
||||
}
|
||||
#startBtn.running:before {
|
||||
content: "Abort";
|
||||
content: attr(data-label-abort);
|
||||
}
|
||||
#resetBtn {
|
||||
display: inline-block;
|
||||
|
|
@ -276,29 +276,29 @@
|
|||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>LibreSpeed - Stability Test</h1>
|
||||
<nav><a href="./">← Speed Test</a></nav>
|
||||
<h1 data-i18n="stability.title">LibreSpeed - Stability Test</h1>
|
||||
<nav><a href="./">← <span data-i18n="stability.back">Speed Test</span></a></nav>
|
||||
|
||||
<div id="controls">
|
||||
<select id="durationSelect">
|
||||
<option value="60">60 Seconds</option>
|
||||
<option value="90">90 Seconds</option>
|
||||
<option value="120">2 Minutes</option>
|
||||
<option value="180">3 Minutes</option>
|
||||
<option value="300">5 Minutes</option>
|
||||
<option value="60" data-i18n="stability.60-seconds">60 Seconds</option>
|
||||
<option value="90" data-i18n="stability.90-seconds">90 Seconds</option>
|
||||
<option value="120" data-i18n="stability.2-minutes">2 Minutes</option>
|
||||
<option value="180" data-i18n="stability.3-minutes">3 Minutes</option>
|
||||
<option value="300" data-i18n="stability.5-minutes">5 Minutes</option>
|
||||
</select>
|
||||
<select id="targetSelect" onchange="updateStartButtonState()">
|
||||
<option value="">Local Server</option>
|
||||
<option value="" data-i18n="stability.local">Local Server</option>
|
||||
<option value="https://www.google.com/generate_204">Google</option>
|
||||
<option value="https://www.cloudflare.com/cdn-cgi/trace">Cloudflare</option>
|
||||
<option value="https://www.apple.com/library/test/success.html">Apple</option>
|
||||
</select>
|
||||
<div id="startBtn" class="disabled finding" onclick="startStop()" aria-disabled="true" title="Finding best server..."></div>
|
||||
<div id="resetBtn" onclick="resetTest()">Reset</div>
|
||||
<div id="startBtn" class="disabled finding" onclick="startStop()" aria-disabled="true" title="Finding best server..." data-label-start="Start" data-label-finding="Finding..." data-label-abort="Abort" data-i18n-attr="title:stability.finding,data-label-start:classic.start,data-label-finding:stability.finding,data-label-abort:classic.abort"></div>
|
||||
<div id="resetBtn" onclick="resetTest()" data-i18n="stability.reset">Reset</div>
|
||||
</div>
|
||||
|
||||
<div id="serverArea" style="display: none">
|
||||
Server:
|
||||
<span data-i18n="stability.server">Server:</span>
|
||||
<select id="server" onchange="onServerChange(this.value)"></select>
|
||||
</div>
|
||||
|
||||
|
|
@ -307,39 +307,39 @@
|
|||
<div id="test">
|
||||
<div class="testGroup">
|
||||
<div class="testArea2">
|
||||
<div class="testName">Current</div>
|
||||
<div class="testName" data-i18n="stability.current">Current</div>
|
||||
<div id="statCurrent" class="meterText" style="color: #aa6060"></div>
|
||||
<div class="unit">ms</div>
|
||||
</div>
|
||||
<div class="testArea2">
|
||||
<div class="testName">Average</div>
|
||||
<div class="testName" data-i18n="stability.average">Average</div>
|
||||
<div id="statAvg" class="meterText" style="color: #aa6060"></div>
|
||||
<div class="unit">ms</div>
|
||||
</div>
|
||||
<div class="testArea2">
|
||||
<div class="testName">Jitter</div>
|
||||
<div class="testName" data-i18n="metric.jitter">Jitter</div>
|
||||
<div id="statJitter" class="meterText" style="color: #aa6060"></div>
|
||||
<div class="unit">ms</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="testGroup">
|
||||
<div class="testArea2">
|
||||
<div class="testName">Min</div>
|
||||
<div class="testName" data-i18n="stability.min">Min</div>
|
||||
<div id="statMin" class="meterText"></div>
|
||||
<div class="unit">ms</div>
|
||||
</div>
|
||||
<div class="testArea2">
|
||||
<div class="testName">Max</div>
|
||||
<div class="testName" data-i18n="stability.max">Max</div>
|
||||
<div id="statMax" class="meterText"></div>
|
||||
<div class="unit">ms</div>
|
||||
</div>
|
||||
<div class="testArea2">
|
||||
<div class="testName">Failed Requests</div>
|
||||
<div class="testName" data-i18n="stability.failed">Failed Requests</div>
|
||||
<div id="statLoss" class="meterText"></div>
|
||||
<div class="unit">%</div>
|
||||
</div>
|
||||
<div class="testArea2">
|
||||
<div class="testName">Elapsed</div>
|
||||
<div class="testName" data-i18n="stability.elapsed">Elapsed</div>
|
||||
<div id="statElapsed" class="meterText">00:00</div>
|
||||
<div class="unit"></div>
|
||||
</div>
|
||||
|
|
@ -352,7 +352,7 @@
|
|||
|
||||
<div id="optionalControls">
|
||||
<label>
|
||||
Alert threshold:
|
||||
<span data-i18n="stability.alert">Alert threshold:</span>
|
||||
<input
|
||||
type="range"
|
||||
id="alertThreshold"
|
||||
|
|
@ -362,13 +362,13 @@
|
|||
value="0"
|
||||
oninput="updateThreshold(this.value)"
|
||||
/>
|
||||
<span id="thresholdValue">Off</span>
|
||||
<span id="thresholdValue" data-i18n="stability.off">Off</span>
|
||||
</label>
|
||||
<button id="downloadCsvBtn" onclick="downloadCsv()">Download CSV</button>
|
||||
<button id="downloadCsvBtn" onclick="downloadCsv()" data-i18n="stability.download-csv">Download CSV</button>
|
||||
</div>
|
||||
|
||||
<div class="footer">
|
||||
<a href="https://github.com/librespeed/speedtest">Source code</a>
|
||||
<a href="https://github.com/librespeed/speedtest" data-i18n="stability.source">Source code</a>
|
||||
</div>
|
||||
|
||||
<script type="text/javascript">
|
||||
|
|
@ -485,7 +485,7 @@
|
|||
I("server").disabled = true;
|
||||
var pendingOpt = document.createElement("option");
|
||||
pendingOpt.value = "";
|
||||
pendingOpt.textContent = "Finding best server...";
|
||||
pendingOpt.textContent = window.LibreSpeedI18n.t("stability.finding-server", "Finding best server...");
|
||||
I("server").appendChild(pendingOpt);
|
||||
updateStartButtonState();
|
||||
// ping servers to find best one
|
||||
|
|
@ -556,7 +556,7 @@
|
|||
var canStart = canStartTest();
|
||||
startBtn.className = canStart ? "" : serverDiscoveryPending ? "disabled finding" : "disabled";
|
||||
startBtn.setAttribute("aria-disabled", canStart ? "false" : "true");
|
||||
startBtn.title = canStart ? "" : serverDiscoveryPending ? "Finding best server..." : "No reachable local server found";
|
||||
startBtn.title = canStart ? "" : serverDiscoveryPending ? window.LibreSpeedI18n.t("stability.finding-server", "Finding best server...") : window.LibreSpeedI18n.t("stability.no-server", "No reachable local server found");
|
||||
I("server").disabled = !localServerReady || serverDiscoveryPending;
|
||||
}
|
||||
|
||||
|
|
@ -693,10 +693,10 @@
|
|||
// Rating calculation
|
||||
function getRating(avg, jit, loss) {
|
||||
if (avg <= 0) return { text: "--", cls: "none" };
|
||||
if (avg < 30 && jit < 5 && loss < 0.5) return { text: "Great", cls: "great" };
|
||||
if (avg < 60 && jit < 15 && loss < 2) return { text: "Good", cls: "good" };
|
||||
if (avg < 100 && jit < 30 && loss < 5) return { text: "Poor", cls: "poor" };
|
||||
return { text: "Bad", cls: "bad" };
|
||||
if (avg < 30 && jit < 5 && loss < 0.5) return { text: window.LibreSpeedI18n.t("stability.great", "Great"), cls: "great" };
|
||||
if (avg < 60 && jit < 15 && loss < 2) return { text: window.LibreSpeedI18n.t("stability.good", "Good"), cls: "good" };
|
||||
if (avg < 100 && jit < 30 && loss < 5) return { text: window.LibreSpeedI18n.t("stability.poor", "Poor"), cls: "poor" };
|
||||
return { text: window.LibreSpeedI18n.t("stability.bad", "Bad"), cls: "bad" };
|
||||
}
|
||||
|
||||
// UI update loop
|
||||
|
|
@ -942,7 +942,7 @@
|
|||
// Alert threshold
|
||||
function updateThreshold(val) {
|
||||
alertThresholdMs = parseInt(val);
|
||||
I("thresholdValue").textContent = alertThresholdMs > 0 ? alertThresholdMs + " ms" : "Off";
|
||||
I("thresholdValue").textContent = alertThresholdMs > 0 ? alertThresholdMs + " ms" : window.LibreSpeedI18n.t("stability.off", "Off");
|
||||
}
|
||||
|
||||
function playBeep() {
|
||||
|
|
@ -987,5 +987,6 @@
|
|||
drawChart();
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
<script defer src="frontend/javascript/i18n.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue