From d1eedd13744f2be27cae5338079955302cd346c3 Mon Sep 17 00:00:00 2001 From: Kristjan ESPERANTO <35647502+KristjanESPERANTO@users.noreply.github.com> Date: Mon, 19 Jan 2026 08:22:25 +0100 Subject: [PATCH 1/3] [core] refactor: extract and centralize HTTP fetcher - Extract HTTP logic from Calendar module into HTTPFetcher class - Migrate calendar module to use centralized HTTPFetcher - Add modern improvements: * AbortController with configurable timeout (default 30s) * undici Agent for self-signed certificates * Improved Retry-After header handling (respects server hints) - Implement intelligent retry strategies: * 401/403: 5x interval, min 30 minutes * 429: Retry-After header parsing, fallback 15 minutes * 5xx: Exponential backoff (max 3 retries) * 4xx: 2x interval, min 15 minutes - Provide structured error objects with translation keys - Comprehensive unit tests with msw (Mock Service Worker) - Tests cover all error scenarios and authentication methods --- js/http_fetcher.js | 300 +++++++++++ modules/default/calendar/calendarfetcher.js | 184 ++----- modules/default/calendar/node_helper.js | 7 +- package-lock.json | 532 ++++++++++++++++++++ package.json | 4 + tests/unit/functions/http_fetcher_spec.js | 443 ++++++++++++++++ translations/af.json | 3 + translations/ar.json | 3 + translations/bg.json | 3 + translations/ca.json | 3 + translations/cs.json | 3 + translations/cv.json | 3 + translations/cy.json | 3 + translations/da.json | 3 + translations/de.json | 3 + translations/el.json | 3 + translations/en.json | 3 + translations/eo.json | 3 + translations/es.json | 3 + translations/et.json | 3 + translations/fi.json | 3 + translations/fr.json | 3 + translations/fy.json | 3 + translations/gl.json | 3 + translations/gu.json | 3 + translations/he.json | 3 + translations/hi.json | 3 + translations/hr.json | 3 + translations/hu.json | 3 + translations/id.json | 3 + translations/is.json | 3 + translations/it.json | 3 + translations/ja.json | 3 + translations/ko.json | 3 + translations/lt.json | 3 + translations/ms-my.json | 3 + translations/nb.json | 3 + translations/nl.json | 3 + translations/nn.json | 3 + translations/pl.json | 3 + translations/pt-br.json | 3 + translations/pt.json | 3 + translations/ro.json | 3 + translations/ru.json | 3 + translations/sk.json | 3 + translations/sv.json | 3 + translations/th.json | 3 + translations/tlh.json | 3 + translations/tr.json | 3 + translations/uk.json | 3 + translations/zh-cn.json | 3 + translations/zh-tw.json | 3 + 52 files changed, 1463 insertions(+), 145 deletions(-) create mode 100644 js/http_fetcher.js create mode 100644 tests/unit/functions/http_fetcher_spec.js diff --git a/js/http_fetcher.js b/js/http_fetcher.js new file mode 100644 index 0000000000..f5a56fc46a --- /dev/null +++ b/js/http_fetcher.js @@ -0,0 +1,300 @@ +const { EventEmitter } = require("node:events"); +const { Agent } = require("undici"); +const Log = require("logger"); +const { getUserAgent } = require("#server_functions"); + +const FIFTEEN_MINUTES = 15 * 60 * 1000; +const THIRTY_MINUTES = 30 * 60 * 1000; +const MAX_SERVER_BACKOFF = 3; +const DEFAULT_TIMEOUT = 30000; // 30 seconds + +/** + * Maps errorType to MagicMirror translation keys. + * This allows HTTPFetcher to provide ready-to-use translation keys, + * eliminating the need to call NodeHelper.checkFetchError(). + */ +const ERROR_TYPE_TO_TRANSLATION = { + AUTH_FAILURE: "MODULE_ERROR_UNAUTHORIZED", + RATE_LIMITED: "MODULE_ERROR_RATE_LIMITED", + SERVER_ERROR: "MODULE_ERROR_SERVER_ERROR", + CLIENT_ERROR: "MODULE_ERROR_CLIENT_ERROR", + NETWORK_ERROR: "MODULE_ERROR_NO_CONNECTION", + UNKNOWN_ERROR: "MODULE_ERROR_UNSPECIFIED" +}; + +/** + * HTTPFetcher - Centralized HTTP fetching with intelligent error handling + * + * Features: + * - Automatic retry strategies based on HTTP status codes + * - Exponential backoff for server errors + * - Retry-After header parsing for rate limiting + * - Authentication support (Basic, Bearer) + * - Self-signed certificate support + * @augments EventEmitter + * @fires HTTPFetcher#response - When fetch succeeds with ok response + * @fires HTTPFetcher#error - When fetch fails or returns non-ok response + * @example + * const fetcher = new HTTPFetcher(url, { reloadInterval: 60000 }); + * fetcher.on('response', (response) => { ... }); + * fetcher.on('error', (errorInfo) => { ... }); + * fetcher.startPeriodicFetch(); + */ +class HTTPFetcher extends EventEmitter { + + /** + * Creates a new HTTPFetcher instance + * @param {string} url - The URL to fetch + * @param {object} options - Configuration options + * @param {number} [options.reloadInterval] - Time in ms between fetches (default: 5 min) + * @param {object} [options.auth] - Authentication options + * @param {string} [options.auth.method] - 'basic' or 'bearer' + * @param {string} [options.auth.user] - Username for basic auth + * @param {string} [options.auth.pass] - Password or token + * @param {boolean} [options.selfSignedCert] - Accept self-signed certificates + * @param {object} [options.headers] - Additional headers to send + * @param {number} [options.maxRetries] - Max retries for 5xx errors (default: 3) + * @param {number} [options.timeout] - Request timeout in ms (default: 30000) + */ + constructor (url, options = {}) { + super(); + + this.url = url; + this.reloadInterval = options.reloadInterval || 5 * 60 * 1000; + this.auth = options.auth || null; + this.selfSignedCert = options.selfSignedCert || false; + this.customHeaders = options.headers || {}; + this.maxRetries = options.maxRetries || MAX_SERVER_BACKOFF; + this.timeout = options.timeout || DEFAULT_TIMEOUT; + + this.reloadTimer = null; + this.serverErrorCount = 0; + } + + /** + * Clears any pending reload timer + */ + clearTimer () { + if (this.reloadTimer) { + clearTimeout(this.reloadTimer); + this.reloadTimer = null; + } + } + + /** + * Schedules the next fetch. + * If no delay is provided, uses reloadInterval. + * If delay is provided but very short (< 1 second), clamps to reloadInterval + * to prevent hammering servers. + * @param {number} [delay] - Delay in milliseconds + */ + scheduleNextFetch (delay) { + let nextDelay = delay ?? this.reloadInterval; + + // Only clamp if delay is unreasonably short (< 1 second) + // This allows respecting Retry-After headers while preventing abuse + if (nextDelay < 1000) { + nextDelay = this.reloadInterval; + } + + // Don't schedule in test mode + if (process.env.mmTestMode === "true") { + return; + } + + this.reloadTimer = setTimeout(() => this.fetch(), nextDelay); + } + + /** + * Starts periodic fetching + */ + startPeriodicFetch () { + this.fetch(); + } + + /** + * Builds the options object for fetch + * @returns {object} Options object containing headers (and dispatcher if needed) + */ + getRequestOptions () { + const headers = { + "User-Agent": getUserAgent(), + ...this.customHeaders + }; + const options = { headers }; + + if (this.selfSignedCert) { + options.dispatcher = new Agent({ + connect: { + rejectUnauthorized: false + } + }); + } + + if (this.auth) { + if (this.auth.method === "bearer") { + headers.Authorization = `Bearer ${this.auth.pass}`; + } else { + headers.Authorization = `Basic ${Buffer.from(`${this.auth.user}:${this.auth.pass}`).toString("base64")}`; + } + } + + return options; + } + + /** + * Parses the Retry-After header value + * @param {string} retryAfter - The Retry-After header value + * @returns {number|null} Milliseconds to wait or null if parsing failed + */ + #parseRetryAfter (retryAfter) { + // Try parsing as seconds + const seconds = Number(retryAfter); + if (!Number.isNaN(seconds) && seconds >= 0) { + return seconds * 1000; + } + + // Try parsing as HTTP-date + const retryDate = Date.parse(retryAfter); + if (!Number.isNaN(retryDate)) { + return Math.max(0, retryDate - Date.now()); + } + + return null; + } + + /** + * Determines the retry delay for a non-ok response + * @param {Response} response - The fetch Response object + * @returns {{delay: number, errorInfo: object}} Computed retry delay and error info + */ + #getDelayForResponse (response) { + const { status } = response; + let delay = this.reloadInterval; + let message = ""; + let errorType = "UNKNOWN_ERROR"; + + if (status === 401 || status === 403) { + errorType = "AUTH_FAILURE"; + delay = Math.max(this.reloadInterval * 5, THIRTY_MINUTES); + message = `Authentication failed (${status}). Waiting ${Math.round(delay / 60000)} minutes before retry.`; + Log.error(`${this.url} - ${message}`); + } else if (status === 429) { + errorType = "RATE_LIMITED"; + const retryAfter = response.headers.get("retry-after"); + const parsed = retryAfter ? this.#parseRetryAfter(retryAfter) : null; + delay = parsed !== null ? Math.max(parsed, this.reloadInterval) : Math.max(this.reloadInterval * 2, FIFTEEN_MINUTES); + message = `Rate limited (429). Retrying in ${Math.round(delay / 60000)} minutes.`; + Log.warn(`${this.url} - ${message}`); + } else if (status >= 500) { + errorType = "SERVER_ERROR"; + this.serverErrorCount = Math.min(this.serverErrorCount + 1, this.maxRetries); + delay = this.reloadInterval * Math.pow(2, this.serverErrorCount); + message = `Server error (${status}). Retry #${this.serverErrorCount} in ${Math.round(delay / 60000)} minutes.`; + Log.error(`${this.url} - ${message}`); + } else if (status >= 400) { + errorType = "CLIENT_ERROR"; + delay = Math.max(this.reloadInterval * 2, FIFTEEN_MINUTES); + message = `Client error (${status}). Retrying in ${Math.round(delay / 60000)} minutes.`; + Log.error(`${this.url} - ${message}`); + } else { + message = `Unexpected HTTP status ${status}.`; + Log.error(`${this.url} - ${message}`); + } + + return { + delay, + errorInfo: this.#createErrorInfo(message, status, errorType, delay) + }; + } + + /** + * Creates a standardized error info object + * @param {string} message - Error message + * @param {number|null} status - HTTP status code or null for network errors + * @param {string} errorType - Error type: AUTH_FAILURE, RATE_LIMITED, SERVER_ERROR, CLIENT_ERROR, NETWORK_ERROR + * @param {number} retryAfter - Delay until next retry in ms + * @param {Error} [originalError] - The original error if any + * @returns {object} Error info object with translationKey for direct use + */ + #createErrorInfo (message, status, errorType, retryAfter, originalError = null) { + return { + message, + status, + errorType, + translationKey: ERROR_TYPE_TO_TRANSLATION[errorType] || "MODULE_ERROR_UNSPECIFIED", + retryAfter, + retryCount: this.serverErrorCount, + url: this.url, + originalError + }; + } + + /** + * Performs the HTTP fetch and emits appropriate events + * @fires HTTPFetcher#response + * @fires HTTPFetcher#error + */ + async fetch () { + this.clearTimer(); + + let nextDelay = this.reloadInterval; + const controller = new AbortController(); + const timeoutId = setTimeout(() => controller.abort(), this.timeout); + + try { + const response = await fetch(this.url, { + ...this.getRequestOptions(), + signal: controller.signal + }); + + if (!response.ok) { + const { delay, errorInfo } = this.#getDelayForResponse(response); + nextDelay = delay; + this.emit("error", errorInfo); + } else { + // Reset server error count on success + this.serverErrorCount = 0; + + /** + * Response event - fired when fetch succeeds + * @event HTTPFetcher#response + * @type {Response} + */ + this.emit("response", response); + } + } catch (error) { + const isTimeout = error.name === "AbortError"; + const message = isTimeout ? `Request timeout after ${this.timeout}ms` : `Network error: ${error.message}`; + + Log.error(`${this.url} - ${message}`); + + const errorInfo = this.#createErrorInfo( + message, + null, + "NETWORK_ERROR", + this.reloadInterval, + error + ); + + /** + * Error event - fired when fetch fails + * @event HTTPFetcher#error + * @type {object} + * @property {string} message - Error description + * @property {number|null} statusCode - HTTP status or null for network errors + * @property {number} retryDelay - Ms until next retry + * @property {number} retryCount - Number of consecutive server errors + * @property {string} url - The URL that was fetched + * @property {Error|null} originalError - The original error + */ + this.emit("error", errorInfo); + } finally { + clearTimeout(timeoutId); + } + + this.scheduleNextFetch(nextDelay); + } +} + +module.exports = HTTPFetcher; diff --git a/modules/default/calendar/calendarfetcher.js b/modules/default/calendar/calendarfetcher.js index cb6cff6773..557f99946c 100644 --- a/modules/default/calendar/calendarfetcher.js +++ b/modules/default/calendar/calendarfetcher.js @@ -2,15 +2,11 @@ const ical = require("node-ical"); const Log = require("logger"); const { Agent } = require("undici"); const CalendarFetcherUtils = require("./calendarfetcherutils"); -const { getUserAgent } = require("#server_functions"); - - -const FIFTEEN_MINUTES = 15 * 60 * 1000; -const THIRTY_MINUTES = 30 * 60 * 1000; -const MAX_SERVER_BACKOFF = 3; +const HTTPFetcher = require("#http_fetcher"); /** - * CalendarFetcher - Fetches and parses iCal calendar data with MagicMirror-focused error handling + * CalendarFetcher - Fetches and parses iCal calendar data + * Uses HTTPFetcher for HTTP handling with intelligent error handling * @class */ class CalendarFetcher { @@ -28,162 +24,68 @@ class CalendarFetcher { */ constructor (url, reloadInterval, excludedEvents, maximumEntries, maximumNumberOfDays, auth, includePastEvents, selfSignedCert) { this.url = url; - this.reloadInterval = reloadInterval; this.excludedEvents = excludedEvents; this.maximumEntries = maximumEntries; this.maximumNumberOfDays = maximumNumberOfDays; - this.auth = auth; this.includePastEvents = includePastEvents; - this.selfSignedCert = selfSignedCert; this.events = []; - this.reloadTimer = null; - this.serverErrorCount = 0; this.lastFetch = null; this.fetchFailedCallback = () => {}; this.eventsReceivedCallback = () => {}; - } - - /** - * Clears any pending reload timer - */ - clearReloadTimer () { - if (this.reloadTimer) { - clearTimeout(this.reloadTimer); - this.reloadTimer = null; - } - } - - /** - * Schedules the next fetch respecting MagicMirror test mode - * @param {number} delay - Delay in milliseconds - */ - scheduleNextFetch (delay) { - const nextDelay = Math.max(delay || this.reloadInterval, this.reloadInterval); - if (process.env.mmTestMode === "true") { - return; - } - this.reloadTimer = setTimeout(() => this.fetchCalendar(), nextDelay); - } - - /** - * Builds the options object for fetch - * @returns {object} Options object containing headers (and agent if needed) - */ - getRequestOptions () { - const headers = { "User-Agent": getUserAgent() }; - const options = { headers }; - - if (this.selfSignedCert) { - options.dispatcher = new Agent({ - connect: { - rejectUnauthorized: false - } - }); - } - if (this.auth) { - if (this.auth.method === "bearer") { - headers.Authorization = `Bearer ${this.auth.pass}`; - } else { - headers.Authorization = `Basic ${Buffer.from(`${this.auth.user}:${this.auth.pass}`).toString("base64")}`; - } - } + // Use HTTPFetcher for HTTP handling (Composition) + this.httpFetcher = new HTTPFetcher(url, { + reloadInterval, + auth, + selfSignedCert + }); - return options; + // Wire up HTTPFetcher events + this.httpFetcher.on("response", (response) => this.#handleResponse(response)); + this.httpFetcher.on("error", (errorInfo) => this.fetchFailedCallback(this, errorInfo)); } /** - * Parses the Retry-After header value - * @param {string} retryAfter - The Retry-After header value - * @returns {number|null} Milliseconds to wait or null if parsing failed + * Handles successful HTTP response + * @param {Response} response - The fetch Response object */ - parseRetryAfter (retryAfter) { - const seconds = Number(retryAfter); - if (!Number.isNaN(seconds) && seconds >= 0) { - return seconds * 1000; - } - - const retryDate = Date.parse(retryAfter); - if (!Number.isNaN(retryDate)) { - return Math.max(0, retryDate - Date.now()); - } + async #handleResponse (response) { + try { + const responseData = await response.text(); + const parsed = ical.parseICS(responseData); - return null; - } + Log.debug(`Parsed iCal data from ${this.url} with ${Object.keys(parsed).length} entries.`); - /** - * Determines the retry delay for a non-ok response - * @param {Response} response - The fetch Response object - * @returns {{delay: number, error: Error}} Error describing the issue and computed retry delay - */ - getDelayForResponse (response) { - const { status, statusText = "" } = response; - let delay = this.reloadInterval; + this.events = CalendarFetcherUtils.filterEvents(parsed, { + excludedEvents: this.excludedEvents, + includePastEvents: this.includePastEvents, + maximumEntries: this.maximumEntries, + maximumNumberOfDays: this.maximumNumberOfDays + }); - if (status === 401 || status === 403) { - delay = Math.max(this.reloadInterval * 5, THIRTY_MINUTES); - Log.error(`${this.url} - Authentication failed (${status}). Waiting ${Math.round(delay / 60000)} minutes before retry.`); - } else if (status === 429) { - const retryAfter = response.headers.get("retry-after"); - const parsed = retryAfter ? this.parseRetryAfter(retryAfter) : null; - delay = parsed !== null ? Math.max(parsed, this.reloadInterval) : Math.max(this.reloadInterval * 2, FIFTEEN_MINUTES); - Log.warn(`${this.url} - Rate limited (429). Retrying in ${Math.round(delay / 60000)} minutes.`); - } else if (status >= 500) { - this.serverErrorCount = Math.min(this.serverErrorCount + 1, MAX_SERVER_BACKOFF); - delay = this.reloadInterval * Math.pow(2, this.serverErrorCount); - Log.error(`${this.url} - Server error (${status}). Retry #${this.serverErrorCount} in ${Math.round(delay / 60000)} minutes.`); - } else if (status >= 400) { - delay = Math.max(this.reloadInterval * 2, FIFTEEN_MINUTES); - Log.error(`${this.url} - Client error (${status}). Retrying in ${Math.round(delay / 60000)} minutes.`); - } else { - Log.error(`${this.url} - Unexpected HTTP status ${status}.`); + this.lastFetch = Date.now(); + this.broadcastEvents(); + } catch (error) { + Log.error(`${this.url} - iCal parsing failed: ${error.message}`); + this.fetchFailedCallback(this, { + message: `iCal parsing failed: ${error.message}`, + status: null, + errorType: "PARSE_ERROR", + translationKey: "MODULE_ERROR_UNSPECIFIED", + retryAfter: this.httpFetcher.reloadInterval, + retryCount: 0, + url: this.url, + originalError: error + }); } - - return { - delay, - error: new Error(`HTTP ${status} ${statusText}`.trim()) - }; } /** - * Fetches and processes calendar data + * Starts fetching calendar data */ - async fetchCalendar () { - this.clearReloadTimer(); - - let nextDelay = this.reloadInterval; - try { - const response = await fetch(this.url, this.getRequestOptions()); - if (!response.ok) { - const { delay, error } = this.getDelayForResponse(response); - nextDelay = delay; - this.fetchFailedCallback(this, error); - } else { - this.serverErrorCount = 0; - const responseData = await response.text(); - try { - const parsed = ical.parseICS(responseData); - Log.debug(`Parsed iCal data from ${this.url} with ${Object.keys(parsed).length} entries.`); - this.events = CalendarFetcherUtils.filterEvents(parsed, { - excludedEvents: this.excludedEvents, - includePastEvents: this.includePastEvents, - maximumEntries: this.maximumEntries, - maximumNumberOfDays: this.maximumNumberOfDays - }); - this.lastFetch = Date.now(); - this.broadcastEvents(); - } catch (error) { - Log.error(`${this.url} - iCal parsing failed: ${error.message}`); - this.fetchFailedCallback(this, error); - } - } - } catch (error) { - Log.error(`${this.url} - Fetch failed: ${error.message}`); - this.fetchFailedCallback(this, error); - } - - this.scheduleNextFetch(nextDelay); + fetchCalendar () { + this.httpFetcher.startPeriodicFetch(); } /** @@ -196,7 +98,7 @@ class CalendarFetcher { return true; } const timeSinceLastFetch = Date.now() - this.lastFetch; - return timeSinceLastFetch >= this.reloadInterval; + return timeSinceLastFetch >= this.httpFetcher.reloadInterval; } /** diff --git a/modules/default/calendar/node_helper.js b/modules/default/calendar/node_helper.js index 5b717b5b1b..de69e4e075 100644 --- a/modules/default/calendar/node_helper.js +++ b/modules/default/calendar/node_helper.js @@ -61,12 +61,11 @@ module.exports = NodeHelper.create({ this.broadcastEvents(fetcher, identifier); }); - fetcher.onError((fetcher, error) => { - Log.error("Calendar Error. Could not fetch calendar: ", fetcher.url, error); - let error_type = NodeHelper.checkFetchError(error); + fetcher.onError((fetcher, errorInfo) => { + Log.error("Calendar Error. Could not fetch calendar: ", fetcher.url, errorInfo.message || errorInfo); this.sendSocketNotification("CALENDAR_ERROR", { id: identifier, - error_type + error_type: errorInfo.translationKey }); }); diff --git a/package-lock.json b/package-lock.json index 4d1422fd61..ec3b15b197 100644 --- a/package-lock.json +++ b/package-lock.json @@ -51,6 +51,7 @@ "jsdom": "^27.4.0", "lint-staged": "^16.2.7", "markdownlint-cli2": "^0.20.0", + "msw": "^2.12.7", "playwright": "^1.57.0", "prettier": "^3.7.4", "prettier-plugin-jinja-template": "^2.1.0", @@ -1894,6 +1895,187 @@ "url": "https://github.com/sponsors/nzakas" } }, + "node_modules/@inquirer/ansi": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@inquirer/ansi/-/ansi-1.0.2.tgz", + "integrity": "sha512-S8qNSZiYzFd0wAcyG5AXCvUHC5Sr7xpZ9wZ2py9XR88jUz8wooStVx5M6dRzczbBWjic9NP7+rY0Xi7qqK/aMQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@inquirer/confirm": { + "version": "5.1.21", + "resolved": "https://registry.npmjs.org/@inquirer/confirm/-/confirm-5.1.21.tgz", + "integrity": "sha512-KR8edRkIsUayMXV+o3Gv+q4jlhENF9nMYUZs9PA2HzrXeHI8M5uDag70U7RJn9yyiMZSbtF5/UexBtAVtZGSbQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@inquirer/core": "^10.3.2", + "@inquirer/type": "^3.0.10" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/core": { + "version": "10.3.2", + "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-10.3.2.tgz", + "integrity": "sha512-43RTuEbfP8MbKzedNqBrlhhNKVwoK//vUFNW3Q3vZ88BLcrs4kYpGg+B2mm5p2K/HfygoCxuKwJJiv8PbGmE0A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@inquirer/ansi": "^1.0.2", + "@inquirer/figures": "^1.0.15", + "@inquirer/type": "^3.0.10", + "cli-width": "^4.1.0", + "mute-stream": "^2.0.0", + "signal-exit": "^4.1.0", + "wrap-ansi": "^6.2.0", + "yoctocolors-cjs": "^2.1.3" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/core/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@inquirer/core/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/@inquirer/core/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@inquirer/core/node_modules/mute-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-2.0.0.tgz", + "integrity": "sha512-WWdIxpyjEn+FhQJQQv9aQAYlHoNVdzIzUySNV1gHUPDSdZJ3yZn7pAAbQcV7B56Mvu881q9FZV+0Vx2xC44VWA==", + "dev": true, + "license": "ISC", + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/@inquirer/core/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@inquirer/core/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@inquirer/core/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@inquirer/core/node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@inquirer/figures": { + "version": "1.0.15", + "resolved": "https://registry.npmjs.org/@inquirer/figures/-/figures-1.0.15.tgz", + "integrity": "sha512-t2IEY+unGHOzAaVM5Xx6DEWKeXlDDcNPeDyUpsRc6CUhBfU3VQOEl+Vssh7VNp1dR8MdUJBWhuObjXCsVpjN5g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@inquirer/type": { + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/@inquirer/type/-/type-3.0.10.tgz", + "integrity": "sha512-BvziSRxfz5Ov8ch0z/n3oijRSEcEsHnhggm4xFZe93DHcUCTlutlq9Ox4SVENAfcRD22UQq7T/atg9Wr3k09eA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, "node_modules/@isaacs/balanced-match": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/@isaacs/balanced-match/-/balanced-match-4.0.1.tgz", @@ -1964,6 +2146,24 @@ "dev": true, "license": "MIT" }, + "node_modules/@mswjs/interceptors": { + "version": "0.40.0", + "resolved": "https://registry.npmjs.org/@mswjs/interceptors/-/interceptors-0.40.0.tgz", + "integrity": "sha512-EFd6cVbHsgLa6wa4RljGj6Wk75qoHxUSyc5asLyyPSyuhIcdS2Q3Phw6ImS1q+CkALthJRShiYfKANcQMuMqsQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@open-draft/deferred-promise": "^2.2.0", + "@open-draft/logger": "^0.3.0", + "@open-draft/until": "^2.0.0", + "is-node-process": "^1.2.0", + "outvariant": "^1.4.3", + "strict-event-emitter": "^0.5.1" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/@napi-rs/wasm-runtime": { "version": "0.2.12", "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.12.tgz", @@ -2015,6 +2215,31 @@ "node": ">= 8" } }, + "node_modules/@open-draft/deferred-promise": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@open-draft/deferred-promise/-/deferred-promise-2.2.0.tgz", + "integrity": "sha512-CecwLWx3rhxVQF6V4bAgPS5t+So2sTbPgAzafKkVizyi7tlwpcFpdFqq+wqF2OwNBmqFuu6tOyouTuxgpMfzmA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@open-draft/logger": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@open-draft/logger/-/logger-0.3.0.tgz", + "integrity": "sha512-X2g45fzhxH238HKO4xbSr7+wBS8Fvw6ixhTDuvLd5mqh6bJJCFAPwU9mPDxbcrRtfxv4u5IHCEH77BmxvXmmxQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-node-process": "^1.2.0", + "outvariant": "^1.4.0" + } + }, + "node_modules/@open-draft/until": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@open-draft/until/-/until-2.1.0.tgz", + "integrity": "sha512-U69T3ItWHvLwGg5eJ0n3I62nWuE6ilHlmz7zM0npLBRvPRd7e6NYmg54vvRtP5mZG7kZqZCFVdsTWo7BPtBujg==", + "dev": true, + "license": "MIT" + }, "node_modules/@pm2/agent": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/@pm2/agent/-/agent-2.1.1.tgz", @@ -2880,6 +3105,13 @@ "@types/node": "*" } }, + "node_modules/@types/statuses": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/statuses/-/statuses-2.0.6.tgz", + "integrity": "sha512-xMAgYwceFhRA2zY+XbEA7mxYbA093wdiW8Vu6gZPGWy9cmOyU9XesH1tNcEWsKFd5Vzrqx5T3D38PWx1FIIXkA==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/unist": { "version": "2.0.11", "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz", @@ -4410,6 +4642,16 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/cli-width": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-4.1.0.tgz", + "integrity": "sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">= 12" + } + }, "node_modules/cliui": { "version": "9.0.1", "resolved": "https://registry.npmjs.org/cliui/-/cliui-9.0.1.tgz", @@ -7038,6 +7280,16 @@ "license": "ISC", "optional": true }, + "node_modules/graphql": { + "version": "16.12.0", + "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.12.0.tgz", + "integrity": "sha512-DKKrynuQRne0PNpEbzuEdHlYOMksHSUI8Zc9Unei5gTsMNA2/vMpoMz/yKba50pejK56qj98qM0SjYxAKi13gQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0" + } + }, "node_modules/handlebars": { "version": "4.7.8", "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz", @@ -7159,6 +7411,13 @@ "node": ">= 0.4" } }, + "node_modules/headers-polyfill": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/headers-polyfill/-/headers-polyfill-4.0.3.tgz", + "integrity": "sha512-IScLbePpkvO846sIwOtOTDjutRMWdXdJmXdMvk6gCBHxFO8d+QKOQedyZSxFTTFYRSmlgSTDtXqqq4pcenBXLQ==", + "dev": true, + "license": "MIT" + }, "node_modules/helmet": { "version": "8.1.0", "resolved": "https://registry.npmjs.org/helmet/-/helmet-8.1.0.tgz", @@ -7762,6 +8021,13 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-node-process": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/is-node-process/-/is-node-process-1.2.0.tgz", + "integrity": "sha512-Vg4o6/fqPxIjtxgUH5QLJhwZ7gW5diGCVlXpuUfELC62CuxM1iHcRe51f2W1FDy04Ai4KJkagKjx3XaqyfRKXw==", + "dev": true, + "license": "MIT" + }, "node_modules/is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", @@ -9319,6 +9585,205 @@ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "license": "MIT" }, + "node_modules/msw": { + "version": "2.12.7", + "resolved": "https://registry.npmjs.org/msw/-/msw-2.12.7.tgz", + "integrity": "sha512-retd5i3xCZDVWMYjHEVuKTmhqY8lSsxujjVrZiGbbdoxxIBg5S7rCuYy/YQpfrTYIxpd/o0Kyb/3H+1udBMoYg==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "@inquirer/confirm": "^5.0.0", + "@mswjs/interceptors": "^0.40.0", + "@open-draft/deferred-promise": "^2.2.0", + "@types/statuses": "^2.0.6", + "cookie": "^1.0.2", + "graphql": "^16.12.0", + "headers-polyfill": "^4.0.2", + "is-node-process": "^1.2.0", + "outvariant": "^1.4.3", + "path-to-regexp": "^6.3.0", + "picocolors": "^1.1.1", + "rettime": "^0.7.0", + "statuses": "^2.0.2", + "strict-event-emitter": "^0.5.1", + "tough-cookie": "^6.0.0", + "type-fest": "^5.2.0", + "until-async": "^3.0.2", + "yargs": "^17.7.2" + }, + "bin": { + "msw": "cli/index.js" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/mswjs" + }, + "peerDependencies": { + "typescript": ">= 4.8.x" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/msw/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/msw/node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/msw/node_modules/cookie": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.1.1.tgz", + "integrity": "sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/msw/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/msw/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/msw/node_modules/path-to-regexp": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.3.0.tgz", + "integrity": "sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/msw/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/msw/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/msw/node_modules/type-fest": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-5.3.1.tgz", + "integrity": "sha512-VCn+LMHbd4t6sF3wfU/+HKT63C9OoyrSIf4b+vtWHpt2U7/4InZG467YDNMFMR70DdHjAdpPWmw2lzRdg0Xqqg==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "dependencies": { + "tagged-tag": "^1.0.0" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/msw/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/msw/node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/msw/node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=12" + } + }, "node_modules/mute-stream": { "version": "0.0.8", "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", @@ -9632,6 +10097,13 @@ "node": ">= 0.8.0" } }, + "node_modules/outvariant": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/outvariant/-/outvariant-1.4.3.tgz", + "integrity": "sha512-+Sl2UErvtsoajRDKCE5/dBz4DIvHXQQnAxtQTF04OJxY0+DyZXSo5P5Bb7XYWOh81syohlYL24hbDwxedPUJCA==", + "dev": true, + "license": "MIT" + }, "node_modules/own-keys": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/own-keys/-/own-keys-1.0.1.tgz", @@ -10619,6 +11091,16 @@ "node": ">= 4.0.0" } }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/require-from-string": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", @@ -10745,6 +11227,13 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/rettime": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/rettime/-/rettime-0.7.0.tgz", + "integrity": "sha512-LPRKoHnLKd/r3dVxcwO7vhCW+orkOGj9ViueosEBK6ie89CijnfRlhaDhHq/3Hxu4CkWQtxwlBG0mzTQY6uQjw==", + "dev": true, + "license": "MIT" + }, "node_modules/reusify": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", @@ -11610,6 +12099,13 @@ "node": ">= 0.4" } }, + "node_modules/strict-event-emitter": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/strict-event-emitter/-/strict-event-emitter-0.5.1.tgz", + "integrity": "sha512-vMgjE/GGEPEFnhFub6pa4FmJBRBVOLpIII2hvCZ8Kzb7K0hlHo7mQv6xYrBvCL2LtAIBwFUK8wvuJgTVSQ5MFQ==", + "dev": true, + "license": "MIT" + }, "node_modules/string-argv": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.2.tgz", @@ -12201,6 +12697,19 @@ "node": ">=8" } }, + "node_modules/tagged-tag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/tagged-tag/-/tagged-tag-1.0.0.tgz", + "integrity": "sha512-yEFYrVhod+hdNyx7g5Bnkkb0G6si8HJurOoOEgC8B/O0uXLHlaey/65KRv6cuWBNhBgHKAROVpc7QyYqE5gFng==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/tinybench": { "version": "2.9.0", "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", @@ -12621,6 +13130,16 @@ "@unrs/resolver-binding-win32-x64-msvc": "1.11.1" } }, + "node_modules/until-async": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/until-async/-/until-async-3.0.2.tgz", + "integrity": "sha512-IiSk4HlzAMqTUseHHe3VhIGyuFmN90zMTpD3Z3y8jeQbzLIq500MVM7Jq2vUAnTKAFPJrqwkzr6PoTcPhGcOiw==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/kettanaito" + } + }, "node_modules/uri-js": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", @@ -13309,6 +13828,19 @@ "funding": { "url": "https://github.com/sponsors/sindresorhus" } + }, + "node_modules/yoctocolors-cjs": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/yoctocolors-cjs/-/yoctocolors-cjs-2.1.3.tgz", + "integrity": "sha512-U/PBtDf35ff0D8X8D0jfdzHYEPFxAI7jJlxZXwCSez5M3190m+QobIfh+sWDWSHMCWWJN2AWamkegn6vr6YBTw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } } } } diff --git a/package.json b/package.json index bf42f2fba9..9512d7f351 100644 --- a/package.json +++ b/package.json @@ -32,6 +32,9 @@ }, "#server_functions": { "default": "./js/server_functions.js" + }, + "#http_fetcher": { + "default": "./js/http_fetcher.js" } }, "main": "js/electron.js", @@ -116,6 +119,7 @@ "jsdom": "^27.4.0", "lint-staged": "^16.2.7", "markdownlint-cli2": "^0.20.0", + "msw": "^2.12.7", "playwright": "^1.57.0", "prettier": "^3.7.4", "prettier-plugin-jinja-template": "^2.1.0", diff --git a/tests/unit/functions/http_fetcher_spec.js b/tests/unit/functions/http_fetcher_spec.js new file mode 100644 index 0000000000..0b05788c2d --- /dev/null +++ b/tests/unit/functions/http_fetcher_spec.js @@ -0,0 +1,443 @@ +const { http, HttpResponse } = require("msw"); +const { setupServer } = require("msw/node"); +const HTTPFetcher = require("#http_fetcher"); + +const TEST_URL = "http://test.example.com/data"; +let server; +let fetcher; + +beforeAll(() => { + server = setupServer(); + server.listen({ onUnhandledRequest: "error" }); +}); + +afterAll(() => { + server.close(); +}); + +afterEach(() => { + server.resetHandlers(); + if (fetcher) { + fetcher.clearTimer(); + fetcher = null; + } +}); + +describe("HTTPFetcher", () => { + + describe("Basic fetch operations", () => { + it("should emit response event on successful fetch", async () => { + const responseData = "test data"; + server.use( + http.get(TEST_URL, () => { + return HttpResponse.text(responseData); + }) + ); + + fetcher = new HTTPFetcher(TEST_URL, { reloadInterval: 60000 }); + + const responsePromise = new Promise((resolve) => { + fetcher.on("response", (response) => { + resolve(response); + }); + }); + + fetcher.startPeriodicFetch(); + const response = await responsePromise; + + expect(response.ok).toBe(true); + expect(response.status).toBe(200); + const text = await response.text(); + expect(text).toBe(responseData); + }); + + it("should emit error event on network failure", async () => { + server.use( + http.get(TEST_URL, () => { + return HttpResponse.error(); + }) + ); + + fetcher = new HTTPFetcher(TEST_URL, { reloadInterval: 60000 }); + + const errorPromise = new Promise((resolve) => { + fetcher.on("error", (errorInfo) => { + resolve(errorInfo); + }); + }); + + fetcher.startPeriodicFetch(); + const errorInfo = await errorPromise; + + expect(errorInfo).toHaveProperty("errorType", "NETWORK_ERROR"); + expect(errorInfo).toHaveProperty("translationKey", "MODULE_ERROR_NO_CONNECTION"); + expect(errorInfo).toHaveProperty("url", TEST_URL); + }); + + it("should emit error event on timeout", async () => { + server.use( + http.get(TEST_URL, async () => { + // Simulate a slow server that never responds + await new Promise((resolve) => setTimeout(resolve, 60000)); + return HttpResponse.text("too late"); + }) + ); + + fetcher = new HTTPFetcher(TEST_URL, { reloadInterval: 60000, timeout: 100 }); + + const errorPromise = new Promise((resolve) => { + fetcher.on("error", (errorInfo) => { + resolve(errorInfo); + }); + }); + + fetcher.startPeriodicFetch(); + const errorInfo = await errorPromise; + + expect(errorInfo.errorType).toBe("NETWORK_ERROR"); + expect(errorInfo.message).toContain("timeout"); + expect(errorInfo.message).toContain("100ms"); + }); + }); + + describe("HTTPFetcher - HTTP status code handling", () => { + describe("401/403 errors (Auth failures)", () => { + it("should emit error with AUTH_FAILURE for 401", async () => { + server.use( + http.get(TEST_URL, () => { + return new HttpResponse(null, { status: 401 }); + }) + ); + + fetcher = new HTTPFetcher(TEST_URL, { reloadInterval: 60000 }); + + const errorPromise = new Promise((resolve) => { + fetcher.on("error", (errorInfo) => { + resolve(errorInfo); + }); + }); + + fetcher.startPeriodicFetch(); + const errorInfo = await errorPromise; + + expect(errorInfo.status).toBe(401); + expect(errorInfo.errorType).toBe("AUTH_FAILURE"); + expect(errorInfo.translationKey).toBe("MODULE_ERROR_UNAUTHORIZED"); + }); + + it("should emit error with AUTH_FAILURE for 403", async () => { + server.use( + http.get(TEST_URL, () => { + return new HttpResponse(null, { status: 403 }); + }) + ); + + fetcher = new HTTPFetcher(TEST_URL, { reloadInterval: 60000 }); + + const errorPromise = new Promise((resolve) => { + fetcher.on("error", (errorInfo) => { + resolve(errorInfo); + }); + }); + + fetcher.startPeriodicFetch(); + const errorInfo = await errorPromise; + + expect(errorInfo.status).toBe(403); + expect(errorInfo.errorType).toBe("AUTH_FAILURE"); + }); + }); + + describe("429 errors (Rate limiting)", () => { + it("should emit error with RATE_LIMITED for 429", async () => { + server.use( + http.get(TEST_URL, () => { + return new HttpResponse(null, { + status: 429, + headers: { "Retry-After": "120" } + }); + }) + ); + + fetcher = new HTTPFetcher(TEST_URL, { reloadInterval: 60000 }); + + const errorPromise = new Promise((resolve) => { + fetcher.on("error", (errorInfo) => { + resolve(errorInfo); + }); + }); + + fetcher.startPeriodicFetch(); + const errorInfo = await errorPromise; + + expect(errorInfo.status).toBe(429); + expect(errorInfo.errorType).toBe("RATE_LIMITED"); + expect(errorInfo.retryAfter).toBeGreaterThan(0); + }); + + it("should parse Retry-After header in seconds", async () => { + server.use( + http.get(TEST_URL, () => { + return new HttpResponse(null, { + status: 429, + headers: { "Retry-After": "300" } + }); + }) + ); + + fetcher = new HTTPFetcher(TEST_URL, { reloadInterval: 60000 }); + + const errorPromise = new Promise((resolve) => { + fetcher.on("error", (errorInfo) => { + resolve(errorInfo); + }); + }); + + fetcher.startPeriodicFetch(); + const errorInfo = await errorPromise; + + // 300 seconds = 300000 ms + expect(errorInfo.retryAfter).toBe(300000); + }); + }); + + describe("5xx errors (Server errors)", () => { + it("should emit error with SERVER_ERROR for 500", async () => { + server.use( + http.get(TEST_URL, () => { + return new HttpResponse(null, { status: 500 }); + }) + ); + + fetcher = new HTTPFetcher(TEST_URL, { reloadInterval: 60000 }); + + const errorPromise = new Promise((resolve) => { + fetcher.on("error", (errorInfo) => { + resolve(errorInfo); + }); + }); + + fetcher.startPeriodicFetch(); + const errorInfo = await errorPromise; + + expect(errorInfo.status).toBe(500); + expect(errorInfo.errorType).toBe("SERVER_ERROR"); + }); + + it("should emit error with SERVER_ERROR for 503", async () => { + server.use( + http.get(TEST_URL, () => { + return new HttpResponse(null, { status: 503 }); + }) + ); + + fetcher = new HTTPFetcher(TEST_URL, { reloadInterval: 60000 }); + + const errorPromise = new Promise((resolve) => { + fetcher.on("error", (errorInfo) => { + resolve(errorInfo); + }); + }); + + fetcher.startPeriodicFetch(); + const errorInfo = await errorPromise; + + expect(errorInfo.status).toBe(503); + expect(errorInfo.errorType).toBe("SERVER_ERROR"); + }); + }); + + describe("4xx errors (Client errors)", () => { + it("should emit error with CLIENT_ERROR for 404", async () => { + server.use( + http.get(TEST_URL, () => { + return new HttpResponse(null, { status: 404 }); + }) + ); + + fetcher = new HTTPFetcher(TEST_URL, { reloadInterval: 60000 }); + + const errorPromise = new Promise((resolve) => { + fetcher.on("error", (errorInfo) => { + resolve(errorInfo); + }); + }); + + fetcher.startPeriodicFetch(); + const errorInfo = await errorPromise; + + expect(errorInfo.status).toBe(404); + expect(errorInfo.errorType).toBe("CLIENT_ERROR"); + }); + }); + }); +}); + +describe("HTTPFetcher - Authentication", () => { + it("should include Basic auth header when configured", async () => { + let receivedHeaders = null; + + server.use( + http.get(TEST_URL, ({ request }) => { + receivedHeaders = Object.fromEntries(request.headers); + return HttpResponse.text("ok"); + }) + ); + + fetcher = new HTTPFetcher(TEST_URL, { + reloadInterval: 60000, + auth: { + method: "basic", + user: "testuser", + pass: "testpass" + } + }); + + const responsePromise = new Promise((resolve) => { + fetcher.on("response", resolve); + }); + + fetcher.startPeriodicFetch(); + await responsePromise; + + const expectedAuth = `Basic ${Buffer.from("testuser:testpass").toString("base64")}`; + expect(receivedHeaders.authorization).toBe(expectedAuth); + }); + + it("should include Bearer auth header when configured", async () => { + let receivedHeaders = null; + + server.use( + http.get(TEST_URL, ({ request }) => { + receivedHeaders = Object.fromEntries(request.headers); + return HttpResponse.text("ok"); + }) + ); + + fetcher = new HTTPFetcher(TEST_URL, { + reloadInterval: 60000, + auth: { + method: "bearer", + pass: "my-token-123" + } + }); + + const responsePromise = new Promise((resolve) => { + fetcher.on("response", resolve); + }); + + fetcher.startPeriodicFetch(); + await responsePromise; + + expect(receivedHeaders.authorization).toBe("Bearer my-token-123"); + }); +}); + +describe("Custom headers", () => { + it("should include custom headers in request", async () => { + let receivedHeaders = null; + + server.use( + http.get(TEST_URL, ({ request }) => { + receivedHeaders = Object.fromEntries(request.headers); + return HttpResponse.text("ok"); + }) + ); + + fetcher = new HTTPFetcher(TEST_URL, { + reloadInterval: 60000, + headers: { + "X-Custom-Header": "custom-value", + Accept: "application/json" + } + }); + + const responsePromise = new Promise((resolve) => { + fetcher.on("response", resolve); + }); + + fetcher.startPeriodicFetch(); + await responsePromise; + + expect(receivedHeaders["x-custom-header"]).toBe("custom-value"); + expect(receivedHeaders.accept).toBe("application/json"); + }); +}); + +describe("Timer management", () => { + it("should not set timer in test mode", async () => { + server.use( + http.get(TEST_URL, () => { + return HttpResponse.text("ok"); + }) + ); + + fetcher = new HTTPFetcher(TEST_URL, { reloadInterval: 100 }); + + const responsePromise = new Promise((resolve) => { + fetcher.on("response", resolve); + }); + + fetcher.startPeriodicFetch(); + await responsePromise; + + // Timer should NOT be set in test mode (mmTestMode=true) + expect(fetcher.reloadTimer).toBeNull(); + }); + + it("should clear timer when clearTimer is called", () => { + fetcher = new HTTPFetcher(TEST_URL, { reloadInterval: 100 }); + + // Manually set a timer to test clearing + fetcher.reloadTimer = setTimeout(() => {}, 10000); + expect(fetcher.reloadTimer).not.toBeNull(); + + fetcher.clearTimer(); + + expect(fetcher.reloadTimer).toBeNull(); + }); +}); + +describe("fetch() method", () => { + it("should emit response event when called", async () => { + const responseData = "direct fetch data"; + server.use( + http.get(TEST_URL, () => { + return HttpResponse.text(responseData); + }) + ); + + fetcher = new HTTPFetcher(TEST_URL, { reloadInterval: 60000 }); + + const responsePromise = new Promise((resolve) => { + fetcher.on("response", resolve); + }); + + await fetcher.fetch(); + const response = await responsePromise; + + expect(response.ok).toBe(true); + const text = await response.text(); + expect(text).toBe(responseData); + }); + + it("should emit error event on network error", async () => { + server.use( + http.get(TEST_URL, () => { + return HttpResponse.error(); + }) + ); + + fetcher = new HTTPFetcher(TEST_URL, { reloadInterval: 60000 }); + + const errorPromise = new Promise((resolve) => { + fetcher.on("error", resolve); + }); + + await fetcher.fetch(); + const errorInfo = await errorPromise; + + expect(errorInfo.errorType).toBe("NETWORK_ERROR"); + }); +}); + diff --git a/translations/af.json b/translations/af.json index 8fb6468020..d6e4eee44f 100644 --- a/translations/af.json +++ b/translations/af.json @@ -36,6 +36,9 @@ "MODULE_ERROR_MALFORMED_URL": "Ongeldige URL.", "MODULE_ERROR_NO_CONNECTION": "Geen internetverbinding.", "MODULE_ERROR_UNAUTHORIZED": "Owerheid het misluk.", + "MODULE_ERROR_RATE_LIMITED": "Too many requests. Retrying later.", + "MODULE_ERROR_SERVER_ERROR": "Server error. Retrying later.", + "MODULE_ERROR_CLIENT_ERROR": "Request failed.", "MODULE_ERROR_UNSPECIFIED": "Gaan die logs na vir meer besonderhede.", "NEWSFEED_NO_ITEMS": "Geen nuus op die oomblik.", diff --git a/translations/ar.json b/translations/ar.json index 968d253283..e91ca0fd84 100644 --- a/translations/ar.json +++ b/translations/ar.json @@ -34,6 +34,9 @@ "MODULE_ERROR_MALFORMED_URL": "رابط غير صحيح.", "MODULE_ERROR_NO_CONNECTION": "لا يوجد اتصال بالإنترنت.", "MODULE_ERROR_UNAUTHORIZED": "فشل التصريح.", + "MODULE_ERROR_RATE_LIMITED": "Too many requests. Retrying later.", + "MODULE_ERROR_SERVER_ERROR": "Server error. Retrying later.", + "MODULE_ERROR_CLIENT_ERROR": "Request failed.", "MODULE_ERROR_UNSPECIFIED": "تحقق من السجلات لمزيد من التفاصيل.", "NEWSFEED_NO_ITEMS": "لا توجد أخبار في الوقت الحالي.", diff --git a/translations/bg.json b/translations/bg.json index 3d742f7a4c..b573b2f3b1 100644 --- a/translations/bg.json +++ b/translations/bg.json @@ -36,6 +36,9 @@ "MODULE_ERROR_MALFORMED_URL": "Неправилен URL адрес.", "MODULE_ERROR_NO_CONNECTION": "Няма интернет връзка.", "MODULE_ERROR_UNAUTHORIZED": "Неуспешна авторизация.", + "MODULE_ERROR_RATE_LIMITED": "Too many requests. Retrying later.", + "MODULE_ERROR_SERVER_ERROR": "Server error. Retrying later.", + "MODULE_ERROR_CLIENT_ERROR": "Request failed.", "MODULE_ERROR_UNSPECIFIED": "Проверете логовете за повече подробности.", "NEWSFEED_NO_ITEMS": "Няма новини в момента.", diff --git a/translations/ca.json b/translations/ca.json index 8be470ad1c..012cba838b 100644 --- a/translations/ca.json +++ b/translations/ca.json @@ -35,6 +35,9 @@ "MODULE_ERROR_MALFORMED_URL": "L'URL és mal format.", "MODULE_ERROR_NO_CONNECTION": "No hi ha connexió a Internet.", "MODULE_ERROR_UNAUTHORIZED": "L'autorització ha fallat.", + "MODULE_ERROR_RATE_LIMITED": "Too many requests. Retrying later.", + "MODULE_ERROR_SERVER_ERROR": "Server error. Retrying later.", + "MODULE_ERROR_CLIENT_ERROR": "Request failed.", "MODULE_ERROR_UNSPECIFIED": "Consulta els registres per a més detalls.", "NEWSFEED_NO_ITEMS": "No hi ha notícies disponibles en aquest moment.", diff --git a/translations/cs.json b/translations/cs.json index 2f16ab1b6e..4f5f592445 100644 --- a/translations/cs.json +++ b/translations/cs.json @@ -36,6 +36,9 @@ "MODULE_ERROR_MALFORMED_URL": "Nesprávná URL adresa.", "MODULE_ERROR_NO_CONNECTION": "Není připojení k internetu.", "MODULE_ERROR_UNAUTHORIZED": "Autorizace selhala.", + "MODULE_ERROR_RATE_LIMITED": "Too many requests. Retrying later.", + "MODULE_ERROR_SERVER_ERROR": "Server error. Retrying later.", + "MODULE_ERROR_CLIENT_ERROR": "Request failed.", "MODULE_ERROR_UNSPECIFIED": "Zkontrolujte protokoly pro více informací.", "NEWSFEED_NO_ITEMS": "Žádné zprávy.", diff --git a/translations/cv.json b/translations/cv.json index 1138d766db..1812b4bac0 100644 --- a/translations/cv.json +++ b/translations/cv.json @@ -35,6 +35,9 @@ "MODULE_ERROR_MALFORMED_URL": "Ҫӗҫ ҫӗнӗ URL хата.", "MODULE_ERROR_NO_CONNECTION": "Интернет-пулла хӗҫҫӗн.", "MODULE_ERROR_UNAUTHORIZED": "Авторизация хата.", + "MODULE_ERROR_RATE_LIMITED": "Too many requests. Retrying later.", + "MODULE_ERROR_SERVER_ERROR": "Server error. Retrying later.", + "MODULE_ERROR_CLIENT_ERROR": "Request failed.", "MODULE_ERROR_UNSPECIFIED": "Тӗп лог ҫӗнтерӗ.", "NEWSFEED_NO_ITEMS": "Пулас ҫӗнтер ҫук.", diff --git a/translations/cy.json b/translations/cy.json index 824d909236..eec99fd94b 100644 --- a/translations/cy.json +++ b/translations/cy.json @@ -35,6 +35,9 @@ "MODULE_ERROR_MALFORMED_URL": "URL anghywir.", "MODULE_ERROR_NO_CONNECTION": "Dim cysylltiad rhyngrwyd.", "MODULE_ERROR_UNAUTHORIZED": "Methiant awdurdodi.", + "MODULE_ERROR_RATE_LIMITED": "Too many requests. Retrying later.", + "MODULE_ERROR_SERVER_ERROR": "Server error. Retrying later.", + "MODULE_ERROR_CLIENT_ERROR": "Request failed.", "MODULE_ERROR_UNSPECIFIED": "Gwiriwch y logiau am ragor o fanylion.", "NEWSFEED_NO_ITEMS": "Dim newyddion ar hyn o bryd.", diff --git a/translations/da.json b/translations/da.json index 13486bfc30..43ef887595 100644 --- a/translations/da.json +++ b/translations/da.json @@ -36,6 +36,9 @@ "MODULE_ERROR_MALFORMED_URL": "Forkert url.", "MODULE_ERROR_NO_CONNECTION": "Ingen internetforbindelse.", "MODULE_ERROR_UNAUTHORIZED": "Godkendelse mislykkedes.", + "MODULE_ERROR_RATE_LIMITED": "Too many requests. Retrying later.", + "MODULE_ERROR_SERVER_ERROR": "Server error. Retrying later.", + "MODULE_ERROR_CLIENT_ERROR": "Request failed.", "MODULE_ERROR_UNSPECIFIED": "Tjek logfiler for flere detaljer.", "NEWSFEED_NO_ITEMS": "Ingen nyheder i øjeblikket.", diff --git a/translations/de.json b/translations/de.json index 86597b1601..69b17b1be4 100644 --- a/translations/de.json +++ b/translations/de.json @@ -37,6 +37,9 @@ "MODULE_ERROR_MALFORMED_URL": "Fehlerhafte URL.", "MODULE_ERROR_NO_CONNECTION": "Keine Internetverbindung.", "MODULE_ERROR_UNAUTHORIZED": "Autorisierung fehlgeschlagen.", + "MODULE_ERROR_RATE_LIMITED": "Zu viele Anfragen. Erneuter Versuch später.", + "MODULE_ERROR_SERVER_ERROR": "Serverfehler. Erneuter Versuch später.", + "MODULE_ERROR_CLIENT_ERROR": "Anfrage fehlgeschlagen.", "MODULE_ERROR_UNSPECIFIED": "Prüfe die Logdateien für weitere Details.", "NEWSFEED_NO_ITEMS": "Momentan keine Neuigkeiten.", diff --git a/translations/el.json b/translations/el.json index 2fd12c90e3..2c28e9ac26 100644 --- a/translations/el.json +++ b/translations/el.json @@ -36,6 +36,9 @@ "MODULE_ERROR_MALFORMED_URL": "Λανθασμένη μορφή url.", "MODULE_ERROR_NO_CONNECTION": "Δεν υπάρχει σύνδεση στο διαδίκτυο.", "MODULE_ERROR_UNAUTHORIZED": "Η εξουσιοδότηση απέτυχε.", + "MODULE_ERROR_RATE_LIMITED": "Too many requests. Retrying later.", + "MODULE_ERROR_SERVER_ERROR": "Server error. Retrying later.", + "MODULE_ERROR_CLIENT_ERROR": "Request failed.", "MODULE_ERROR_UNSPECIFIED": "Ελέγξτε τα αρχεία καταγραφής για περισσότερες λεπτομέρειες.", "NEWSFEED_NO_ITEMS": "Δεν υπάρχουν ειδήσεις αυτή τη στιγμή.", diff --git a/translations/en.json b/translations/en.json index c4a2f196df..9e95afa348 100644 --- a/translations/en.json +++ b/translations/en.json @@ -35,6 +35,9 @@ "MODULE_ERROR_MALFORMED_URL": "Malformed url.", "MODULE_ERROR_NO_CONNECTION": "No internet connection.", "MODULE_ERROR_UNAUTHORIZED": "Authorization failed.", + "MODULE_ERROR_RATE_LIMITED": "Too many requests. Retrying later.", + "MODULE_ERROR_SERVER_ERROR": "Server error. Retrying later.", + "MODULE_ERROR_CLIENT_ERROR": "Request failed.", "MODULE_ERROR_UNSPECIFIED": "Check logs for more details.", "NEWSFEED_NO_ITEMS": "No news at the moment.", diff --git a/translations/eo.json b/translations/eo.json index a5730d8243..824282cd33 100644 --- a/translations/eo.json +++ b/translations/eo.json @@ -37,6 +37,9 @@ "MODULE_ERROR_MALFORMED_URL": "Malĝusta URL.", "MODULE_ERROR_NO_CONNECTION": "Neniu interreta konekto.", "MODULE_ERROR_UNAUTHORIZED": "Aŭtorigo malsukcesis.", + "MODULE_ERROR_RATE_LIMITED": "Tro multaj petoj. Reprovo poste.", + "MODULE_ERROR_SERVER_ERROR": "Servila eraro. Reprovo poste.", + "MODULE_ERROR_CLIENT_ERROR": "Peto malsukcesis.", "MODULE_ERROR_UNSPECIFIED": "Kontrolu la protokolajn dosierojn por pli da detaloj.", "NEWSFEED_NO_ITEMS": "Momente neniu novaĵoj.", diff --git a/translations/es.json b/translations/es.json index 4106d45d74..336add235b 100644 --- a/translations/es.json +++ b/translations/es.json @@ -37,6 +37,9 @@ "MODULE_ERROR_MALFORMED_URL": "URL mal formado.", "MODULE_ERROR_NO_CONNECTION": "No hay conexión a Internet.", "MODULE_ERROR_UNAUTHORIZED": "No autorizado.", + "MODULE_ERROR_RATE_LIMITED": "Too many requests. Retrying later.", + "MODULE_ERROR_SERVER_ERROR": "Server error. Retrying later.", + "MODULE_ERROR_CLIENT_ERROR": "Request failed.", "MODULE_ERROR_UNSPECIFIED": "Por favor, consulte los registros para obtener más información.", "NEWSFEED_NO_ITEMS": "No hay noticias disponibles en este momento.", diff --git a/translations/et.json b/translations/et.json index cd3d5ebe7a..8df8abeff4 100644 --- a/translations/et.json +++ b/translations/et.json @@ -36,6 +36,9 @@ "MODULE_ERROR_MALFORMED_URL": "Ebakorrektne url.", "MODULE_ERROR_NO_CONNECTION": "Interneti ühendus puudub.", "MODULE_ERROR_UNAUTHORIZED": "Autoriseerimine ebaõnnestus.", + "MODULE_ERROR_RATE_LIMITED": "Too many requests. Retrying later.", + "MODULE_ERROR_SERVER_ERROR": "Server error. Retrying later.", + "MODULE_ERROR_CLIENT_ERROR": "Request failed.", "MODULE_ERROR_UNSPECIFIED": "Lisateabe saamiseks kontrollige logifaile.", "NEWSFEED_NO_ITEMS": "Hetkel ei ole uudiseid.", diff --git a/translations/fi.json b/translations/fi.json index c29ae33310..ca54e6b025 100644 --- a/translations/fi.json +++ b/translations/fi.json @@ -36,6 +36,9 @@ "MODULE_ERROR_MALFORMED_URL": "Virheellinen url.", "MODULE_ERROR_NO_CONNECTION": "Ei internet-yhteyttä.", "MODULE_ERROR_UNAUTHORIZED": "Valtuutus epäonnistui.", + "MODULE_ERROR_RATE_LIMITED": "Too many requests. Retrying later.", + "MODULE_ERROR_SERVER_ERROR": "Server error. Retrying later.", + "MODULE_ERROR_CLIENT_ERROR": "Request failed.", "MODULE_ERROR_UNSPECIFIED": "Tarkista lokitiedostot saadaksesi lisätietoja.", "NEWSFEED_NO_ITEMS": "Ei uutisia tällä hetkellä.", diff --git a/translations/fr.json b/translations/fr.json index 226f454fcf..4f258dad62 100644 --- a/translations/fr.json +++ b/translations/fr.json @@ -37,6 +37,9 @@ "MODULE_ERROR_MALFORMED_URL": "URL mal formée.", "MODULE_ERROR_NO_CONNECTION": "Pas de connexion Internet.", "MODULE_ERROR_UNAUTHORIZED": "L'autorisation à échouée.", + "MODULE_ERROR_RATE_LIMITED": "Too many requests. Retrying later.", + "MODULE_ERROR_SERVER_ERROR": "Server error. Retrying later.", + "MODULE_ERROR_CLIENT_ERROR": "Request failed.", "MODULE_ERROR_UNSPECIFIED": "Consultez les journaux pour plus de détails.", "NEWSFEED_NO_ITEMS": "Aucune nouvelle pour le moment.", diff --git a/translations/fy.json b/translations/fy.json index b261bd1cfd..4c64fc8959 100644 --- a/translations/fy.json +++ b/translations/fy.json @@ -35,6 +35,9 @@ "MODULE_ERROR_MALFORMED_URL": "De URL is net jildich.", "MODULE_ERROR_NO_CONNECTION": "Gjin ynternetferbining.", "MODULE_ERROR_UNAUTHORIZED": "Autorisearje mislearre.", + "MODULE_ERROR_RATE_LIMITED": "Too many requests. Retrying later.", + "MODULE_ERROR_SERVER_ERROR": "Server error. Retrying later.", + "MODULE_ERROR_CLIENT_ERROR": "Request failed.", "MODULE_ERROR_UNSPECIFIED": "Sjoch de logs foar mear ynformaasje.", "NEWSFEED_NO_ITEMS": "Op it stuit gjin nijsberjochten.", diff --git a/translations/gl.json b/translations/gl.json index 8225a1a4c4..dd331ae780 100644 --- a/translations/gl.json +++ b/translations/gl.json @@ -36,6 +36,9 @@ "MODULE_ERROR_MALFORMED_URL": "URL mal formado.", "MODULE_ERROR_NO_CONNECTION": "Non hai conexión a Internet.", "MODULE_ERROR_UNAUTHORIZED": "A autorización fallou.", + "MODULE_ERROR_RATE_LIMITED": "Too many requests. Retrying later.", + "MODULE_ERROR_SERVER_ERROR": "Server error. Retrying later.", + "MODULE_ERROR_CLIENT_ERROR": "Request failed.", "MODULE_ERROR_UNSPECIFIED": "Verifique os rexistros para obter máis información.", "NEWSFEED_NO_ITEMS": "Non hai novas no momento.", diff --git a/translations/gu.json b/translations/gu.json index 7b55ee9078..0623668a09 100644 --- a/translations/gu.json +++ b/translations/gu.json @@ -36,6 +36,9 @@ "MODULE_ERROR_MALFORMED_URL": "ખોટી URL.", "MODULE_ERROR_NO_CONNECTION": "ઇન્ટરનેટ કનેક્શન નથી.", "MODULE_ERROR_UNAUTHORIZED": "અધિકૃત કરવું નિષ્ફળ.", + "MODULE_ERROR_RATE_LIMITED": "Too many requests. Retrying later.", + "MODULE_ERROR_SERVER_ERROR": "Server error. Retrying later.", + "MODULE_ERROR_CLIENT_ERROR": "Request failed.", "MODULE_ERROR_UNSPECIFIED": "વધુ વિગતો માટે લોગ તપાસો.", "NEWSFEED_NO_ITEMS": "હાલમાં કોઈ સમાચાર નથી.", diff --git a/translations/he.json b/translations/he.json index 6acd490f4a..ae8bad92ee 100644 --- a/translations/he.json +++ b/translations/he.json @@ -36,6 +36,9 @@ "MODULE_ERROR_MALFORMED_URL": "כתובת אתר לא תקינה.", "MODULE_ERROR_NO_CONNECTION": "אין חיבור לאינטרנט.", "MODULE_ERROR_UNAUTHORIZED": "הזדהות נכשלה.", + "MODULE_ERROR_RATE_LIMITED": "Too many requests. Retrying later.", + "MODULE_ERROR_SERVER_ERROR": "Server error. Retrying later.", + "MODULE_ERROR_CLIENT_ERROR": "Request failed.", "MODULE_ERROR_UNSPECIFIED": "בדוק את היומנים לפרטים נוספים.", "NEWSFEED_NO_ITEMS": "אין חדשות כרגע.", diff --git a/translations/hi.json b/translations/hi.json index 725a8a89f8..f58c0ca1f1 100644 --- a/translations/hi.json +++ b/translations/hi.json @@ -36,6 +36,9 @@ "MODULE_ERROR_MALFORMED_URL": "गलत URL।", "MODULE_ERROR_NO_CONNECTION": "कोई इंटरनेट कनेक्शन नहीं।", "MODULE_ERROR_UNAUTHORIZED": "प्राधिकरण विफल।", + "MODULE_ERROR_RATE_LIMITED": "Too many requests. Retrying later.", + "MODULE_ERROR_SERVER_ERROR": "Server error. Retrying later.", + "MODULE_ERROR_CLIENT_ERROR": "Request failed.", "MODULE_ERROR_UNSPECIFIED": "अधिक जानकारी के लिए लॉग जांचें।", "NEWSFEED_NO_ITEMS": "इस समय कोई समाचार नहीं।", diff --git a/translations/hr.json b/translations/hr.json index 8964aeaa95..67b525d5d1 100644 --- a/translations/hr.json +++ b/translations/hr.json @@ -36,6 +36,9 @@ "MODULE_ERROR_MALFORMED_URL": "Neispravan URL.", "MODULE_ERROR_NO_CONNECTION": "Nema internetske veze.", "MODULE_ERROR_UNAUTHORIZED": "Autorizacija nije uspjela.", + "MODULE_ERROR_RATE_LIMITED": "Too many requests. Retrying later.", + "MODULE_ERROR_SERVER_ERROR": "Server error. Retrying later.", + "MODULE_ERROR_CLIENT_ERROR": "Request failed.", "MODULE_ERROR_UNSPECIFIED": "Provjerite dnevnike za više informacija.", "NEWSFEED_NO_ITEMS": "Trenutno nema vijesti.", diff --git a/translations/hu.json b/translations/hu.json index 2c31349b7b..8c35436eee 100644 --- a/translations/hu.json +++ b/translations/hu.json @@ -35,6 +35,9 @@ "MODULE_ERROR_MALFORMED_URL": "Hibás URL.", "MODULE_ERROR_NO_CONNECTION": "Nincs internetkapcsolat.", "MODULE_ERROR_UNAUTHORIZED": "Azonosítás sikertelen.", + "MODULE_ERROR_RATE_LIMITED": "Too many requests. Retrying later.", + "MODULE_ERROR_SERVER_ERROR": "Server error. Retrying later.", + "MODULE_ERROR_CLIENT_ERROR": "Request failed.", "MODULE_ERROR_UNSPECIFIED": "Ellenőrizze a naplókat további részletekért.", "NEWSFEED_NO_ITEMS": "Jelenleg nincsenek hírek.", diff --git a/translations/id.json b/translations/id.json index 4bb83eb93c..f0669572b1 100644 --- a/translations/id.json +++ b/translations/id.json @@ -35,6 +35,9 @@ "MODULE_ERROR_MALFORMED_URL": "URL tidak valid.", "MODULE_ERROR_NO_CONNECTION": "Tidak ada koneksi internet.", "MODULE_ERROR_UNAUTHORIZED": "Gagal otentikasi.", + "MODULE_ERROR_RATE_LIMITED": "Too many requests. Retrying later.", + "MODULE_ERROR_SERVER_ERROR": "Server error. Retrying later.", + "MODULE_ERROR_CLIENT_ERROR": "Request failed.", "MODULE_ERROR_UNSPECIFIED": "Silakan periksa log untuk informasi lebih lanjut.", "NEWSFEED_NO_ITEMS": "Saat ini tidak ada berita.", diff --git a/translations/is.json b/translations/is.json index d664a9f284..a3f1b203ed 100644 --- a/translations/is.json +++ b/translations/is.json @@ -36,6 +36,9 @@ "MODULE_ERROR_MALFORMED_URL": "Villa í slóð.", "MODULE_ERROR_NO_CONNECTION": "Engin nettenging.", "MODULE_ERROR_UNAUTHORIZED": "Auðkenning mistókst.", + "MODULE_ERROR_RATE_LIMITED": "Too many requests. Retrying later.", + "MODULE_ERROR_SERVER_ERROR": "Server error. Retrying later.", + "MODULE_ERROR_CLIENT_ERROR": "Request failed.", "MODULE_ERROR_UNSPECIFIED": "Vinsamlegast athugaðu skráningu fyrir frekari upplýsingar.", "NEWSFEED_NO_ITEMS": "Engar fréttir í boði núna.", diff --git a/translations/it.json b/translations/it.json index 78051638ee..687c6a0b1d 100644 --- a/translations/it.json +++ b/translations/it.json @@ -35,6 +35,9 @@ "MODULE_ERROR_MALFORMED_URL": "URL non valido.", "MODULE_ERROR_NO_CONNECTION": "Nessuna connessione a Internet.", "MODULE_ERROR_UNAUTHORIZED": "Autenticazione non riuscita.", + "MODULE_ERROR_RATE_LIMITED": "Too many requests. Retrying later.", + "MODULE_ERROR_SERVER_ERROR": "Server error. Retrying later.", + "MODULE_ERROR_CLIENT_ERROR": "Request failed.", "MODULE_ERROR_UNSPECIFIED": "Si prega di controllare i log per ulteriori dettagli.", "NEWSFEED_NO_ITEMS": "Al momento non ci sono notizie.", diff --git a/translations/ja.json b/translations/ja.json index e74da77cbc..6a22788f89 100644 --- a/translations/ja.json +++ b/translations/ja.json @@ -36,6 +36,9 @@ "MODULE_ERROR_MALFORMED_URL": "不正なURLです。", "MODULE_ERROR_NO_CONNECTION": "インターネット接続がありません。", "MODULE_ERROR_UNAUTHORIZED": "認証に失敗しました。", + "MODULE_ERROR_RATE_LIMITED": "Too many requests. Retrying later.", + "MODULE_ERROR_SERVER_ERROR": "Server error. Retrying later.", + "MODULE_ERROR_CLIENT_ERROR": "Request failed.", "MODULE_ERROR_UNSPECIFIED": "詳細はログを確認してください。", "NEWSFEED_NO_ITEMS": "現在ニュースはありません。", diff --git a/translations/ko.json b/translations/ko.json index 0e6bbd5ed5..b59af38c6f 100644 --- a/translations/ko.json +++ b/translations/ko.json @@ -36,6 +36,9 @@ "MODULE_ERROR_MALFORMED_URL": "잘못된 URL 형식입니다.", "MODULE_ERROR_NO_CONNECTION": "인터넷이 연결되지 않았습니다.", "MODULE_ERROR_UNAUTHORIZED": "인증이 실패했습니다.", + "MODULE_ERROR_RATE_LIMITED": "Too many requests. Retrying later.", + "MODULE_ERROR_SERVER_ERROR": "Server error. Retrying later.", + "MODULE_ERROR_CLIENT_ERROR": "Request failed.", "MODULE_ERROR_UNSPECIFIED": "상세 내용은 로그를 확인하세요.", "NEWSFEED_NO_ITEMS": "현재 뉴스가 없습니다.", diff --git a/translations/lt.json b/translations/lt.json index b922b5193e..429513c254 100644 --- a/translations/lt.json +++ b/translations/lt.json @@ -36,6 +36,9 @@ "MODULE_ERROR_MALFORMED_URL": "Netinkama URL nuoroda.", "MODULE_ERROR_NO_CONNECTION": "Nėra interneto ryšio.", "MODULE_ERROR_UNAUTHORIZED": "Autorizacija nepavyko.", + "MODULE_ERROR_RATE_LIMITED": "Too many requests. Retrying later.", + "MODULE_ERROR_SERVER_ERROR": "Server error. Retrying later.", + "MODULE_ERROR_CLIENT_ERROR": "Request failed.", "MODULE_ERROR_UNSPECIFIED": "Patikrinkite žurnalus, kad gautumėte daugiau informacijos.", "NEWSFEED_NO_ITEMS": "Šiuo metu naujienų nėra.", diff --git a/translations/ms-my.json b/translations/ms-my.json index d3e7a9565f..9f8b5b21cc 100644 --- a/translations/ms-my.json +++ b/translations/ms-my.json @@ -36,6 +36,9 @@ "MODULE_ERROR_MALFORMED_URL": "URL tidak sah.", "MODULE_ERROR_NO_CONNECTION": "Tiada sambungan internet.", "MODULE_ERROR_UNAUTHORIZED": "Kebenaran gagal.", + "MODULE_ERROR_RATE_LIMITED": "Too many requests. Retrying later.", + "MODULE_ERROR_SERVER_ERROR": "Server error. Retrying later.", + "MODULE_ERROR_CLIENT_ERROR": "Request failed.", "MODULE_ERROR_UNSPECIFIED": "Sila semak log untuk maklumat lanjut.", "NEWSFEED_NO_ITEMS": "Tiada berita buat masa ini.", diff --git a/translations/nb.json b/translations/nb.json index 8eac3eec0f..007620f1b3 100644 --- a/translations/nb.json +++ b/translations/nb.json @@ -36,6 +36,9 @@ "MODULE_ERROR_MALFORMED_URL": "Ugyldig URL.", "MODULE_ERROR_NO_CONNECTION": "Ingen internettforbindelse.", "MODULE_ERROR_UNAUTHORIZED": "Autentisering mislyktes.", + "MODULE_ERROR_RATE_LIMITED": "Too many requests. Retrying later.", + "MODULE_ERROR_SERVER_ERROR": "Server error. Retrying later.", + "MODULE_ERROR_CLIENT_ERROR": "Request failed.", "MODULE_ERROR_UNSPECIFIED": "Vennligst sjekk loggene for mer informasjon.", "NEWSFEED_NO_ITEMS": "Ingen nyheter tilgjengelig for øyeblikket.", diff --git a/translations/nl.json b/translations/nl.json index 26d55fab95..419922298f 100644 --- a/translations/nl.json +++ b/translations/nl.json @@ -36,6 +36,9 @@ "MODULE_ERROR_MALFORMED_URL": "Ongeldige url.", "MODULE_ERROR_NO_CONNECTION": "Geen internet verbinding.", "MODULE_ERROR_UNAUTHORIZED": "Authenticatie mislukt.", + "MODULE_ERROR_RATE_LIMITED": "Too many requests. Retrying later.", + "MODULE_ERROR_SERVER_ERROR": "Server error. Retrying later.", + "MODULE_ERROR_CLIENT_ERROR": "Request failed.", "MODULE_ERROR_UNSPECIFIED": "Bekijk de logs voor meer informatie.", "NEWSFEED_NO_ITEMS": "Geen nieuws op dit moment.", diff --git a/translations/nn.json b/translations/nn.json index ce97e29bf7..8b0a6164d4 100644 --- a/translations/nn.json +++ b/translations/nn.json @@ -36,6 +36,9 @@ "MODULE_ERROR_MALFORMED_URL": "Ugyldig URL.", "MODULE_ERROR_NO_CONNECTION": "Ingen internettforbindelse.", "MODULE_ERROR_UNAUTHORIZED": "Autentisering mislyktes.", + "MODULE_ERROR_RATE_LIMITED": "Too many requests. Retrying later.", + "MODULE_ERROR_SERVER_ERROR": "Server error. Retrying later.", + "MODULE_ERROR_CLIENT_ERROR": "Request failed.", "MODULE_ERROR_UNSPECIFIED": "Vennligst sjekk loggfilene for meir informasjon.", "NEWSFEED_NO_ITEMS": "Ingen nyhende tilgjengeleg no.", diff --git a/translations/pl.json b/translations/pl.json index f12bde0abb..2659283842 100644 --- a/translations/pl.json +++ b/translations/pl.json @@ -36,6 +36,9 @@ "MODULE_ERROR_MALFORMED_URL": "Nieprawidłowy adres URL.", "MODULE_ERROR_NO_CONNECTION": "Brak połączenia z internetem.", "MODULE_ERROR_UNAUTHORIZED": "Autoryzacja nie powiodła się.", + "MODULE_ERROR_RATE_LIMITED": "Too many requests. Retrying later.", + "MODULE_ERROR_SERVER_ERROR": "Server error. Retrying later.", + "MODULE_ERROR_CLIENT_ERROR": "Request failed.", "MODULE_ERROR_UNSPECIFIED": "Sprawdź logi, aby uzyskać więcej informacji.", "NEWSFEED_NO_ITEMS": "Brak wiadomości w tej chwili.", diff --git a/translations/pt-br.json b/translations/pt-br.json index 1a7ecafcb0..3fd5db07c2 100644 --- a/translations/pt-br.json +++ b/translations/pt-br.json @@ -35,6 +35,9 @@ "MODULE_ERROR_MALFORMED_URL": "URL inválido.", "MODULE_ERROR_NO_CONNECTION": "Sem conexão com a Internet.", "MODULE_ERROR_UNAUTHORIZED": "Falha na autenticação.", + "MODULE_ERROR_RATE_LIMITED": "Too many requests. Retrying later.", + "MODULE_ERROR_SERVER_ERROR": "Server error. Retrying later.", + "MODULE_ERROR_CLIENT_ERROR": "Request failed.", "MODULE_ERROR_UNSPECIFIED": "Verifique os logs para mais detalhes.", "NEWSFEED_NO_ITEMS": "Atualmente não há notícias.", diff --git a/translations/pt.json b/translations/pt.json index c6c6105c84..9d931aadc0 100644 --- a/translations/pt.json +++ b/translations/pt.json @@ -37,6 +37,9 @@ "MODULE_ERROR_MALFORMED_URL": "URL inválido.", "MODULE_ERROR_NO_CONNECTION": "Sem ligação à internet.", "MODULE_ERROR_UNAUTHORIZED": "Falha na autorização.", + "MODULE_ERROR_RATE_LIMITED": "Too many requests. Retrying later.", + "MODULE_ERROR_SERVER_ERROR": "Server error. Retrying later.", + "MODULE_ERROR_CLIENT_ERROR": "Request failed.", "MODULE_ERROR_UNSPECIFIED": "Consulta os registos para mais detalhes.", "NEWSFEED_NO_ITEMS": "Sem notícias de momento.", diff --git a/translations/ro.json b/translations/ro.json index 1dfa6f5d5e..86ca0d4d99 100644 --- a/translations/ro.json +++ b/translations/ro.json @@ -36,6 +36,9 @@ "MODULE_ERROR_MALFORMED_URL": "URL incorect.", "MODULE_ERROR_NO_CONNECTION": "Fără conexiune la internet.", "MODULE_ERROR_UNAUTHORIZED": "Autorizarea a eșuat.", + "MODULE_ERROR_RATE_LIMITED": "Too many requests. Retrying later.", + "MODULE_ERROR_SERVER_ERROR": "Server error. Retrying later.", + "MODULE_ERROR_CLIENT_ERROR": "Request failed.", "MODULE_ERROR_UNSPECIFIED": "Verificați jurnalele pentru mai multe detalii.", "NEWSFEED_NO_ITEMS": "Nu există știri în acest moment.", diff --git a/translations/ru.json b/translations/ru.json index fde2fe81e2..c8c550a0ca 100644 --- a/translations/ru.json +++ b/translations/ru.json @@ -36,6 +36,9 @@ "MODULE_ERROR_MALFORMED_URL": "Неверный URL.", "MODULE_ERROR_NO_CONNECTION": "Нет интернет-соединения.", "MODULE_ERROR_UNAUTHORIZED": "Не удалось авторизоваться.", + "MODULE_ERROR_RATE_LIMITED": "Too many requests. Retrying later.", + "MODULE_ERROR_SERVER_ERROR": "Server error. Retrying later.", + "MODULE_ERROR_CLIENT_ERROR": "Request failed.", "MODULE_ERROR_UNSPECIFIED": "Пожалуйста, проверьте логи для получения дополнительной информации.", "NEWSFEED_NO_ITEMS": "В данный момент нет новостей.", diff --git a/translations/sk.json b/translations/sk.json index 1736d0cc3c..1217a94b6f 100644 --- a/translations/sk.json +++ b/translations/sk.json @@ -36,6 +36,9 @@ "MODULE_ERROR_MALFORMED_URL": "Nesprávna URL adresa.", "MODULE_ERROR_NO_CONNECTION": "Nie je pripojenie k internetu.", "MODULE_ERROR_UNAUTHORIZED": "Autorizácia zlyhala.", + "MODULE_ERROR_RATE_LIMITED": "Too many requests. Retrying later.", + "MODULE_ERROR_SERVER_ERROR": "Server error. Retrying later.", + "MODULE_ERROR_CLIENT_ERROR": "Request failed.", "MODULE_ERROR_UNSPECIFIED": "Skontrolujte protokoly pre viac informácií.", "NEWSFEED_NO_ITEMS": "Momentálne žiadne správy.", diff --git a/translations/sv.json b/translations/sv.json index 5a6961ffa4..5f98105d4b 100644 --- a/translations/sv.json +++ b/translations/sv.json @@ -36,6 +36,9 @@ "MODULE_ERROR_MALFORMED_URL": "Felaktig URL.", "MODULE_ERROR_NO_CONNECTION": "Ingen internetanslutning.", "MODULE_ERROR_UNAUTHORIZED": "Autentisering misslyckades.", + "MODULE_ERROR_RATE_LIMITED": "Too many requests. Retrying later.", + "MODULE_ERROR_SERVER_ERROR": "Server error. Retrying later.", + "MODULE_ERROR_CLIENT_ERROR": "Request failed.", "MODULE_ERROR_UNSPECIFIED": "Vänligen kontrollera loggarna för mer information.", "NEWSFEED_NO_ITEMS": "Inga nyheter för tillfället.", diff --git a/translations/th.json b/translations/th.json index 6a9965ac45..2a1dfbd2ec 100644 --- a/translations/th.json +++ b/translations/th.json @@ -36,6 +36,9 @@ "MODULE_ERROR_MALFORMED_URL": "URL ผิดรูปแบบ", "MODULE_ERROR_NO_CONNECTION": "ไม่มีการเชื่อมต่ออินเทอร์เน็ต.", "MODULE_ERROR_UNAUTHORIZED": "การอนุญาตล้มเหลว", + "MODULE_ERROR_RATE_LIMITED": "Too many requests. Retrying later.", + "MODULE_ERROR_SERVER_ERROR": "Server error. Retrying later.", + "MODULE_ERROR_CLIENT_ERROR": "Request failed.", "MODULE_ERROR_UNSPECIFIED": "ตรวจสอบบันทึกสำหรับรายละเอียดเพิ่มเติม", "NEWSFEED_NO_ITEMS": "ไม่มีข่าวในขณะนี้", diff --git a/translations/tlh.json b/translations/tlh.json index 05d24c5b1f..a6813c8c72 100644 --- a/translations/tlh.json +++ b/translations/tlh.json @@ -36,6 +36,9 @@ "MODULE_ERROR_MALFORMED_URL": "URL ghobe' yImev.", "MODULE_ERROR_NO_CONNECTION": "Internet ghobe' yImev.", "MODULE_ERROR_UNAUTHORIZED": "ghobe' yImev.", + "MODULE_ERROR_RATE_LIMITED": "Too many requests. Retrying later.", + "MODULE_ERROR_SERVER_ERROR": "Server error. Retrying later.", + "MODULE_ERROR_CLIENT_ERROR": "Request failed.", "MODULE_ERROR_UNSPECIFIED": "logmeyDaq yImev.", "NEWSFEED_NO_ITEMS": "DaHghachmey ghobe' yImev.", diff --git a/translations/tr.json b/translations/tr.json index 08f0690401..5e044277f8 100644 --- a/translations/tr.json +++ b/translations/tr.json @@ -35,6 +35,9 @@ "MODULE_ERROR_MALFORMED_URL": "Hatalı URL.", "MODULE_ERROR_NO_CONNECTION": "İnternet bağlantısı yok.", "MODULE_ERROR_UNAUTHORIZED": "Yetkilendirme başarısız.", + "MODULE_ERROR_RATE_LIMITED": "Too many requests. Retrying later.", + "MODULE_ERROR_SERVER_ERROR": "Server error. Retrying later.", + "MODULE_ERROR_CLIENT_ERROR": "Request failed.", "MODULE_ERROR_UNSPECIFIED": "Daha fazla ayrıntı için günlükleri kontrol edin.", "NEWSFEED_NO_ITEMS": "Şu anda haber yok.", diff --git a/translations/uk.json b/translations/uk.json index 70f5a3cbac..35d4c665e3 100644 --- a/translations/uk.json +++ b/translations/uk.json @@ -36,6 +36,9 @@ "MODULE_ERROR_MALFORMED_URL": "Неправильний URL.", "MODULE_ERROR_NO_CONNECTION": "Немає підключення до Інтернету.", "MODULE_ERROR_UNAUTHORIZED": "Авторизація не вдалася.", + "MODULE_ERROR_RATE_LIMITED": "Too many requests. Retrying later.", + "MODULE_ERROR_SERVER_ERROR": "Server error. Retrying later.", + "MODULE_ERROR_CLIENT_ERROR": "Request failed.", "MODULE_ERROR_UNSPECIFIED": "Перевірте журнали для отримання додаткової інформації.", "NEWSFEED_NO_ITEMS": "Немає новин на даний момент.", diff --git a/translations/zh-cn.json b/translations/zh-cn.json index 7ece692365..94ddb45b3f 100644 --- a/translations/zh-cn.json +++ b/translations/zh-cn.json @@ -36,6 +36,9 @@ "MODULE_ERROR_MALFORMED_URL": "URL格式错误。", "MODULE_ERROR_NO_CONNECTION": "无网络连接。", "MODULE_ERROR_UNAUTHORIZED": "授权失败。", + "MODULE_ERROR_RATE_LIMITED": "Too many requests. Retrying later.", + "MODULE_ERROR_SERVER_ERROR": "Server error. Retrying later.", + "MODULE_ERROR_CLIENT_ERROR": "Request failed.", "MODULE_ERROR_UNSPECIFIED": "请查看日志以获取更多详细信息。", "NEWSFEED_NO_ITEMS": "目前没有新闻。", diff --git a/translations/zh-tw.json b/translations/zh-tw.json index 8b6a9dac38..f1e3d2c1e0 100644 --- a/translations/zh-tw.json +++ b/translations/zh-tw.json @@ -36,6 +36,9 @@ "MODULE_ERROR_MALFORMED_URL": "網址格式錯誤。", "MODULE_ERROR_NO_CONNECTION": "無網路連線。", "MODULE_ERROR_UNAUTHORIZED": "授權失敗。", + "MODULE_ERROR_RATE_LIMITED": "Too many requests. Retrying later.", + "MODULE_ERROR_SERVER_ERROR": "Server error. Retrying later.", + "MODULE_ERROR_CLIENT_ERROR": "Request failed.", "MODULE_ERROR_UNSPECIFIED": "查看日誌以了解詳情。", "NEWSFEED_NO_ITEMS": "目前沒有新聞。", From 98ac34597e1db4af95a3d5cc4384318e1c0c2e94 Mon Sep 17 00:00:00 2001 From: Kristjan ESPERANTO <35647502+KristjanESPERANTO@users.noreply.github.com> Date: Wed, 21 Jan 2026 11:06:14 +0100 Subject: [PATCH 2/3] i18n: translate new messages --- translations/af.json | 6 +++--- translations/ar.json | 6 +++--- translations/bg.json | 6 +++--- translations/ca.json | 6 +++--- translations/cs.json | 6 +++--- translations/cv.json | 6 +++--- translations/cy.json | 6 +++--- translations/da.json | 6 +++--- translations/el.json | 6 +++--- translations/es.json | 6 +++--- translations/et.json | 6 +++--- translations/fi.json | 6 +++--- translations/fr.json | 6 +++--- translations/fy.json | 6 +++--- translations/gl.json | 6 +++--- translations/gu.json | 6 +++--- translations/he.json | 6 +++--- translations/hi.json | 6 +++--- translations/hr.json | 6 +++--- translations/hu.json | 6 +++--- translations/id.json | 6 +++--- translations/is.json | 6 +++--- translations/it.json | 6 +++--- translations/ja.json | 6 +++--- translations/ko.json | 6 +++--- translations/lt.json | 6 +++--- translations/ms-my.json | 6 +++--- translations/nb.json | 6 +++--- translations/nl.json | 6 +++--- translations/nn.json | 6 +++--- translations/pl.json | 6 +++--- translations/pt-br.json | 6 +++--- translations/pt.json | 6 +++--- translations/ro.json | 6 +++--- translations/ru.json | 6 +++--- translations/sk.json | 6 +++--- translations/sv.json | 6 +++--- translations/th.json | 6 +++--- translations/tlh.json | 6 +++--- translations/tr.json | 6 +++--- translations/uk.json | 6 +++--- translations/zh-cn.json | 6 +++--- translations/zh-tw.json | 6 +++--- 43 files changed, 129 insertions(+), 129 deletions(-) diff --git a/translations/af.json b/translations/af.json index d6e4eee44f..149e90a6be 100644 --- a/translations/af.json +++ b/translations/af.json @@ -36,9 +36,9 @@ "MODULE_ERROR_MALFORMED_URL": "Ongeldige URL.", "MODULE_ERROR_NO_CONNECTION": "Geen internetverbinding.", "MODULE_ERROR_UNAUTHORIZED": "Owerheid het misluk.", - "MODULE_ERROR_RATE_LIMITED": "Too many requests. Retrying later.", - "MODULE_ERROR_SERVER_ERROR": "Server error. Retrying later.", - "MODULE_ERROR_CLIENT_ERROR": "Request failed.", + "MODULE_ERROR_RATE_LIMITED": "Te veel versoeke. Probeer later weer.", + "MODULE_ERROR_SERVER_ERROR": "Bediener fout. Probeer later weer.", + "MODULE_ERROR_CLIENT_ERROR": "Versoek het misluk.", "MODULE_ERROR_UNSPECIFIED": "Gaan die logs na vir meer besonderhede.", "NEWSFEED_NO_ITEMS": "Geen nuus op die oomblik.", diff --git a/translations/ar.json b/translations/ar.json index e91ca0fd84..a0b7c09a7a 100644 --- a/translations/ar.json +++ b/translations/ar.json @@ -34,9 +34,9 @@ "MODULE_ERROR_MALFORMED_URL": "رابط غير صحيح.", "MODULE_ERROR_NO_CONNECTION": "لا يوجد اتصال بالإنترنت.", "MODULE_ERROR_UNAUTHORIZED": "فشل التصريح.", - "MODULE_ERROR_RATE_LIMITED": "Too many requests. Retrying later.", - "MODULE_ERROR_SERVER_ERROR": "Server error. Retrying later.", - "MODULE_ERROR_CLIENT_ERROR": "Request failed.", + "MODULE_ERROR_RATE_LIMITED": "طلبات كثيرة جدا. إعادة المحاولة لاحقا.", + "MODULE_ERROR_SERVER_ERROR": "خطأ في الخادم. إعادة المحاولة لاحقا.", + "MODULE_ERROR_CLIENT_ERROR": "فشل الطلب.", "MODULE_ERROR_UNSPECIFIED": "تحقق من السجلات لمزيد من التفاصيل.", "NEWSFEED_NO_ITEMS": "لا توجد أخبار في الوقت الحالي.", diff --git a/translations/bg.json b/translations/bg.json index b573b2f3b1..1f6b5eab55 100644 --- a/translations/bg.json +++ b/translations/bg.json @@ -36,9 +36,9 @@ "MODULE_ERROR_MALFORMED_URL": "Неправилен URL адрес.", "MODULE_ERROR_NO_CONNECTION": "Няма интернет връзка.", "MODULE_ERROR_UNAUTHORIZED": "Неуспешна авторизация.", - "MODULE_ERROR_RATE_LIMITED": "Too many requests. Retrying later.", - "MODULE_ERROR_SERVER_ERROR": "Server error. Retrying later.", - "MODULE_ERROR_CLIENT_ERROR": "Request failed.", + "MODULE_ERROR_RATE_LIMITED": "Твърде много заявки. Повторен опит по-късно.", + "MODULE_ERROR_SERVER_ERROR": "Грешка в сървъра. Повторен опит по-късно.", + "MODULE_ERROR_CLIENT_ERROR": "Заявката неуспешна.", "MODULE_ERROR_UNSPECIFIED": "Проверете логовете за повече подробности.", "NEWSFEED_NO_ITEMS": "Няма новини в момента.", diff --git a/translations/ca.json b/translations/ca.json index 012cba838b..f9b5a0e63a 100644 --- a/translations/ca.json +++ b/translations/ca.json @@ -35,9 +35,9 @@ "MODULE_ERROR_MALFORMED_URL": "L'URL és mal format.", "MODULE_ERROR_NO_CONNECTION": "No hi ha connexió a Internet.", "MODULE_ERROR_UNAUTHORIZED": "L'autorització ha fallat.", - "MODULE_ERROR_RATE_LIMITED": "Too many requests. Retrying later.", - "MODULE_ERROR_SERVER_ERROR": "Server error. Retrying later.", - "MODULE_ERROR_CLIENT_ERROR": "Request failed.", + "MODULE_ERROR_RATE_LIMITED": "Masses sol·licituds. Reintentant més tard.", + "MODULE_ERROR_SERVER_ERROR": "Error del servidor. Reintentant més tard.", + "MODULE_ERROR_CLIENT_ERROR": "La sol·licitud ha fallat.", "MODULE_ERROR_UNSPECIFIED": "Consulta els registres per a més detalls.", "NEWSFEED_NO_ITEMS": "No hi ha notícies disponibles en aquest moment.", diff --git a/translations/cs.json b/translations/cs.json index 4f5f592445..931ea113a5 100644 --- a/translations/cs.json +++ b/translations/cs.json @@ -36,9 +36,9 @@ "MODULE_ERROR_MALFORMED_URL": "Nesprávná URL adresa.", "MODULE_ERROR_NO_CONNECTION": "Není připojení k internetu.", "MODULE_ERROR_UNAUTHORIZED": "Autorizace selhala.", - "MODULE_ERROR_RATE_LIMITED": "Too many requests. Retrying later.", - "MODULE_ERROR_SERVER_ERROR": "Server error. Retrying later.", - "MODULE_ERROR_CLIENT_ERROR": "Request failed.", + "MODULE_ERROR_RATE_LIMITED": "Příliš mnoho požadavků. Zkouším znovu později.", + "MODULE_ERROR_SERVER_ERROR": "Chyba serveru. Zkouším znovu později.", + "MODULE_ERROR_CLIENT_ERROR": "Požadavek selhal.", "MODULE_ERROR_UNSPECIFIED": "Zkontrolujte protokoly pro více informací.", "NEWSFEED_NO_ITEMS": "Žádné zprávy.", diff --git a/translations/cv.json b/translations/cv.json index 1812b4bac0..6e4eafb3b6 100644 --- a/translations/cv.json +++ b/translations/cv.json @@ -35,9 +35,9 @@ "MODULE_ERROR_MALFORMED_URL": "Ҫӗҫ ҫӗнӗ URL хата.", "MODULE_ERROR_NO_CONNECTION": "Интернет-пулла хӗҫҫӗн.", "MODULE_ERROR_UNAUTHORIZED": "Авторизация хата.", - "MODULE_ERROR_RATE_LIMITED": "Too many requests. Retrying later.", - "MODULE_ERROR_SERVER_ERROR": "Server error. Retrying later.", - "MODULE_ERROR_CLIENT_ERROR": "Request failed.", + "MODULE_ERROR_RATE_LIMITED": "Нумай ыйту. Хыҫра тепӗр хут.", + "MODULE_ERROR_SERVER_ERROR": "Сервер хатӗ. Хыҫра тепӗр хут.", + "MODULE_ERROR_CLIENT_ERROR": "Ыйту хатӗ.", "MODULE_ERROR_UNSPECIFIED": "Тӗп лог ҫӗнтерӗ.", "NEWSFEED_NO_ITEMS": "Пулас ҫӗнтер ҫук.", diff --git a/translations/cy.json b/translations/cy.json index eec99fd94b..39395f3d09 100644 --- a/translations/cy.json +++ b/translations/cy.json @@ -35,9 +35,9 @@ "MODULE_ERROR_MALFORMED_URL": "URL anghywir.", "MODULE_ERROR_NO_CONNECTION": "Dim cysylltiad rhyngrwyd.", "MODULE_ERROR_UNAUTHORIZED": "Methiant awdurdodi.", - "MODULE_ERROR_RATE_LIMITED": "Too many requests. Retrying later.", - "MODULE_ERROR_SERVER_ERROR": "Server error. Retrying later.", - "MODULE_ERROR_CLIENT_ERROR": "Request failed.", + "MODULE_ERROR_RATE_LIMITED": "Gormod o geisiadau. Yn ceisio eto yn nes ymlaen.", + "MODULE_ERROR_SERVER_ERROR": "Gwall gweinydd. Yn ceisio eto yn nes ymlaen.", + "MODULE_ERROR_CLIENT_ERROR": "Cais wedi methu.", "MODULE_ERROR_UNSPECIFIED": "Gwiriwch y logiau am ragor o fanylion.", "NEWSFEED_NO_ITEMS": "Dim newyddion ar hyn o bryd.", diff --git a/translations/da.json b/translations/da.json index 43ef887595..edc650c2e9 100644 --- a/translations/da.json +++ b/translations/da.json @@ -36,9 +36,9 @@ "MODULE_ERROR_MALFORMED_URL": "Forkert url.", "MODULE_ERROR_NO_CONNECTION": "Ingen internetforbindelse.", "MODULE_ERROR_UNAUTHORIZED": "Godkendelse mislykkedes.", - "MODULE_ERROR_RATE_LIMITED": "Too many requests. Retrying later.", - "MODULE_ERROR_SERVER_ERROR": "Server error. Retrying later.", - "MODULE_ERROR_CLIENT_ERROR": "Request failed.", + "MODULE_ERROR_RATE_LIMITED": "For mange anmodninger. Prøver igen senere.", + "MODULE_ERROR_SERVER_ERROR": "Serverfejl. Prøver igen senere.", + "MODULE_ERROR_CLIENT_ERROR": "Anmodning mislykkedes.", "MODULE_ERROR_UNSPECIFIED": "Tjek logfiler for flere detaljer.", "NEWSFEED_NO_ITEMS": "Ingen nyheder i øjeblikket.", diff --git a/translations/el.json b/translations/el.json index 2c28e9ac26..10146303f4 100644 --- a/translations/el.json +++ b/translations/el.json @@ -36,9 +36,9 @@ "MODULE_ERROR_MALFORMED_URL": "Λανθασμένη μορφή url.", "MODULE_ERROR_NO_CONNECTION": "Δεν υπάρχει σύνδεση στο διαδίκτυο.", "MODULE_ERROR_UNAUTHORIZED": "Η εξουσιοδότηση απέτυχε.", - "MODULE_ERROR_RATE_LIMITED": "Too many requests. Retrying later.", - "MODULE_ERROR_SERVER_ERROR": "Server error. Retrying later.", - "MODULE_ERROR_CLIENT_ERROR": "Request failed.", + "MODULE_ERROR_RATE_LIMITED": "Πάρα πολλά αιτήματα. Θα ξαναπροσπαθήσω αργότερα.", + "MODULE_ERROR_SERVER_ERROR": "Σφάλμα διακομιστή. Θα ξαναπροσπαθήσω αργότερα.", + "MODULE_ERROR_CLIENT_ERROR": "Το αίτημα απέτυχε.", "MODULE_ERROR_UNSPECIFIED": "Ελέγξτε τα αρχεία καταγραφής για περισσότερες λεπτομέρειες.", "NEWSFEED_NO_ITEMS": "Δεν υπάρχουν ειδήσεις αυτή τη στιγμή.", diff --git a/translations/es.json b/translations/es.json index 336add235b..30e06e7881 100644 --- a/translations/es.json +++ b/translations/es.json @@ -37,9 +37,9 @@ "MODULE_ERROR_MALFORMED_URL": "URL mal formado.", "MODULE_ERROR_NO_CONNECTION": "No hay conexión a Internet.", "MODULE_ERROR_UNAUTHORIZED": "No autorizado.", - "MODULE_ERROR_RATE_LIMITED": "Too many requests. Retrying later.", - "MODULE_ERROR_SERVER_ERROR": "Server error. Retrying later.", - "MODULE_ERROR_CLIENT_ERROR": "Request failed.", + "MODULE_ERROR_RATE_LIMITED": "Demasiadas solicitudes. Reintentando más tarde.", + "MODULE_ERROR_SERVER_ERROR": "Error del servidor. Reintentando más tarde.", + "MODULE_ERROR_CLIENT_ERROR": "La solicitud falló.", "MODULE_ERROR_UNSPECIFIED": "Por favor, consulte los registros para obtener más información.", "NEWSFEED_NO_ITEMS": "No hay noticias disponibles en este momento.", diff --git a/translations/et.json b/translations/et.json index 8df8abeff4..cf9e0099ed 100644 --- a/translations/et.json +++ b/translations/et.json @@ -36,9 +36,9 @@ "MODULE_ERROR_MALFORMED_URL": "Ebakorrektne url.", "MODULE_ERROR_NO_CONNECTION": "Interneti ühendus puudub.", "MODULE_ERROR_UNAUTHORIZED": "Autoriseerimine ebaõnnestus.", - "MODULE_ERROR_RATE_LIMITED": "Too many requests. Retrying later.", - "MODULE_ERROR_SERVER_ERROR": "Server error. Retrying later.", - "MODULE_ERROR_CLIENT_ERROR": "Request failed.", + "MODULE_ERROR_RATE_LIMITED": "Liiga palju päringuid. Proovin hiljem uuesti.", + "MODULE_ERROR_SERVER_ERROR": "Serveri viga. Proovin hiljem uuesti.", + "MODULE_ERROR_CLIENT_ERROR": "Päring ebaõnnestus.", "MODULE_ERROR_UNSPECIFIED": "Lisateabe saamiseks kontrollige logifaile.", "NEWSFEED_NO_ITEMS": "Hetkel ei ole uudiseid.", diff --git a/translations/fi.json b/translations/fi.json index ca54e6b025..c201fbb8e0 100644 --- a/translations/fi.json +++ b/translations/fi.json @@ -36,9 +36,9 @@ "MODULE_ERROR_MALFORMED_URL": "Virheellinen url.", "MODULE_ERROR_NO_CONNECTION": "Ei internet-yhteyttä.", "MODULE_ERROR_UNAUTHORIZED": "Valtuutus epäonnistui.", - "MODULE_ERROR_RATE_LIMITED": "Too many requests. Retrying later.", - "MODULE_ERROR_SERVER_ERROR": "Server error. Retrying later.", - "MODULE_ERROR_CLIENT_ERROR": "Request failed.", + "MODULE_ERROR_RATE_LIMITED": "Liikaa pyyntöjä. Yritetään myöhemmin uudelleen.", + "MODULE_ERROR_SERVER_ERROR": "Palvelinvirhe. Yritetään myöhemmin uudelleen.", + "MODULE_ERROR_CLIENT_ERROR": "Pyyntö epäonnistui.", "MODULE_ERROR_UNSPECIFIED": "Tarkista lokitiedostot saadaksesi lisätietoja.", "NEWSFEED_NO_ITEMS": "Ei uutisia tällä hetkellä.", diff --git a/translations/fr.json b/translations/fr.json index 4f258dad62..e4c05e7985 100644 --- a/translations/fr.json +++ b/translations/fr.json @@ -37,9 +37,9 @@ "MODULE_ERROR_MALFORMED_URL": "URL mal formée.", "MODULE_ERROR_NO_CONNECTION": "Pas de connexion Internet.", "MODULE_ERROR_UNAUTHORIZED": "L'autorisation à échouée.", - "MODULE_ERROR_RATE_LIMITED": "Too many requests. Retrying later.", - "MODULE_ERROR_SERVER_ERROR": "Server error. Retrying later.", - "MODULE_ERROR_CLIENT_ERROR": "Request failed.", + "MODULE_ERROR_RATE_LIMITED": "Trop de requêtes. Nouvelle tentative plus tard.", + "MODULE_ERROR_SERVER_ERROR": "Erreur du serveur. Nouvelle tentative plus tard.", + "MODULE_ERROR_CLIENT_ERROR": "La requête a échoué.", "MODULE_ERROR_UNSPECIFIED": "Consultez les journaux pour plus de détails.", "NEWSFEED_NO_ITEMS": "Aucune nouvelle pour le moment.", diff --git a/translations/fy.json b/translations/fy.json index 4c64fc8959..939002669f 100644 --- a/translations/fy.json +++ b/translations/fy.json @@ -35,9 +35,9 @@ "MODULE_ERROR_MALFORMED_URL": "De URL is net jildich.", "MODULE_ERROR_NO_CONNECTION": "Gjin ynternetferbining.", "MODULE_ERROR_UNAUTHORIZED": "Autorisearje mislearre.", - "MODULE_ERROR_RATE_LIMITED": "Too many requests. Retrying later.", - "MODULE_ERROR_SERVER_ERROR": "Server error. Retrying later.", - "MODULE_ERROR_CLIENT_ERROR": "Request failed.", + "MODULE_ERROR_RATE_LIMITED": "Te folle fersiken. Letter opnij besykje.", + "MODULE_ERROR_SERVER_ERROR": "Tsjinnerfout. Letter opnij besykje.", + "MODULE_ERROR_CLIENT_ERROR": "Fersyk mislearre.", "MODULE_ERROR_UNSPECIFIED": "Sjoch de logs foar mear ynformaasje.", "NEWSFEED_NO_ITEMS": "Op it stuit gjin nijsberjochten.", diff --git a/translations/gl.json b/translations/gl.json index dd331ae780..7d410971da 100644 --- a/translations/gl.json +++ b/translations/gl.json @@ -36,9 +36,9 @@ "MODULE_ERROR_MALFORMED_URL": "URL mal formado.", "MODULE_ERROR_NO_CONNECTION": "Non hai conexión a Internet.", "MODULE_ERROR_UNAUTHORIZED": "A autorización fallou.", - "MODULE_ERROR_RATE_LIMITED": "Too many requests. Retrying later.", - "MODULE_ERROR_SERVER_ERROR": "Server error. Retrying later.", - "MODULE_ERROR_CLIENT_ERROR": "Request failed.", + "MODULE_ERROR_RATE_LIMITED": "Demasiadas solicitudes. Reintentando máis tarde.", + "MODULE_ERROR_SERVER_ERROR": "Erro do servidor. Reintentando máis tarde.", + "MODULE_ERROR_CLIENT_ERROR": "A solicitude fallou.", "MODULE_ERROR_UNSPECIFIED": "Verifique os rexistros para obter máis información.", "NEWSFEED_NO_ITEMS": "Non hai novas no momento.", diff --git a/translations/gu.json b/translations/gu.json index 0623668a09..32ea8ce350 100644 --- a/translations/gu.json +++ b/translations/gu.json @@ -36,9 +36,9 @@ "MODULE_ERROR_MALFORMED_URL": "ખોટી URL.", "MODULE_ERROR_NO_CONNECTION": "ઇન્ટરનેટ કનેક્શન નથી.", "MODULE_ERROR_UNAUTHORIZED": "અધિકૃત કરવું નિષ્ફળ.", - "MODULE_ERROR_RATE_LIMITED": "Too many requests. Retrying later.", - "MODULE_ERROR_SERVER_ERROR": "Server error. Retrying later.", - "MODULE_ERROR_CLIENT_ERROR": "Request failed.", + "MODULE_ERROR_RATE_LIMITED": "ઘણી બધી વિનંતીઓ. પછીથી પુનઃપ્રયાસ.", + "MODULE_ERROR_SERVER_ERROR": "સર્વર ભૂલ. પછીથી પુનઃપ્રયાસ.", + "MODULE_ERROR_CLIENT_ERROR": "વિનંતી નિષ્ફળ.", "MODULE_ERROR_UNSPECIFIED": "વધુ વિગતો માટે લોગ તપાસો.", "NEWSFEED_NO_ITEMS": "હાલમાં કોઈ સમાચાર નથી.", diff --git a/translations/he.json b/translations/he.json index ae8bad92ee..998504c2ed 100644 --- a/translations/he.json +++ b/translations/he.json @@ -36,9 +36,9 @@ "MODULE_ERROR_MALFORMED_URL": "כתובת אתר לא תקינה.", "MODULE_ERROR_NO_CONNECTION": "אין חיבור לאינטרנט.", "MODULE_ERROR_UNAUTHORIZED": "הזדהות נכשלה.", - "MODULE_ERROR_RATE_LIMITED": "Too many requests. Retrying later.", - "MODULE_ERROR_SERVER_ERROR": "Server error. Retrying later.", - "MODULE_ERROR_CLIENT_ERROR": "Request failed.", + "MODULE_ERROR_RATE_LIMITED": "יותר מדי בקשות. מנסה שוב מאוחר יותר.", + "MODULE_ERROR_SERVER_ERROR": "שגיאת שרת. מנסה שוב מאוחר יותר.", + "MODULE_ERROR_CLIENT_ERROR": "הבקשה נכשלה.", "MODULE_ERROR_UNSPECIFIED": "בדוק את היומנים לפרטים נוספים.", "NEWSFEED_NO_ITEMS": "אין חדשות כרגע.", diff --git a/translations/hi.json b/translations/hi.json index f58c0ca1f1..890b2ebd3b 100644 --- a/translations/hi.json +++ b/translations/hi.json @@ -36,9 +36,9 @@ "MODULE_ERROR_MALFORMED_URL": "गलत URL।", "MODULE_ERROR_NO_CONNECTION": "कोई इंटरनेट कनेक्शन नहीं।", "MODULE_ERROR_UNAUTHORIZED": "प्राधिकरण विफल।", - "MODULE_ERROR_RATE_LIMITED": "Too many requests. Retrying later.", - "MODULE_ERROR_SERVER_ERROR": "Server error. Retrying later.", - "MODULE_ERROR_CLIENT_ERROR": "Request failed.", + "MODULE_ERROR_RATE_LIMITED": "बहुत सारे अनुरोध। बाद में पुनः प्रयास करना।", + "MODULE_ERROR_SERVER_ERROR": "सर्वर त्रुटि। बाद में पुनः प्रयास करना।", + "MODULE_ERROR_CLIENT_ERROR": "अनुरोध विफल रहा।", "MODULE_ERROR_UNSPECIFIED": "अधिक जानकारी के लिए लॉग जांचें।", "NEWSFEED_NO_ITEMS": "इस समय कोई समाचार नहीं।", diff --git a/translations/hr.json b/translations/hr.json index 67b525d5d1..18c01e24d5 100644 --- a/translations/hr.json +++ b/translations/hr.json @@ -36,9 +36,9 @@ "MODULE_ERROR_MALFORMED_URL": "Neispravan URL.", "MODULE_ERROR_NO_CONNECTION": "Nema internetske veze.", "MODULE_ERROR_UNAUTHORIZED": "Autorizacija nije uspjela.", - "MODULE_ERROR_RATE_LIMITED": "Too many requests. Retrying later.", - "MODULE_ERROR_SERVER_ERROR": "Server error. Retrying later.", - "MODULE_ERROR_CLIENT_ERROR": "Request failed.", + "MODULE_ERROR_RATE_LIMITED": "Previše zahtjeva. Ponovni pokušaj kasnije.", + "MODULE_ERROR_SERVER_ERROR": "Greška poslužitelja. Ponovni pokušaj kasnije.", + "MODULE_ERROR_CLIENT_ERROR": "Zahtjev nije uspio.", "MODULE_ERROR_UNSPECIFIED": "Provjerite dnevnike za više informacija.", "NEWSFEED_NO_ITEMS": "Trenutno nema vijesti.", diff --git a/translations/hu.json b/translations/hu.json index 8c35436eee..db96e63051 100644 --- a/translations/hu.json +++ b/translations/hu.json @@ -35,9 +35,9 @@ "MODULE_ERROR_MALFORMED_URL": "Hibás URL.", "MODULE_ERROR_NO_CONNECTION": "Nincs internetkapcsolat.", "MODULE_ERROR_UNAUTHORIZED": "Azonosítás sikertelen.", - "MODULE_ERROR_RATE_LIMITED": "Too many requests. Retrying later.", - "MODULE_ERROR_SERVER_ERROR": "Server error. Retrying later.", - "MODULE_ERROR_CLIENT_ERROR": "Request failed.", + "MODULE_ERROR_RATE_LIMITED": "Túl sok kérés. Újrapróbálkozás később.", + "MODULE_ERROR_SERVER_ERROR": "Szerverhiba. Újrapróbálkozás később.", + "MODULE_ERROR_CLIENT_ERROR": "A kérés meghiúsult.", "MODULE_ERROR_UNSPECIFIED": "Ellenőrizze a naplókat további részletekért.", "NEWSFEED_NO_ITEMS": "Jelenleg nincsenek hírek.", diff --git a/translations/id.json b/translations/id.json index f0669572b1..c5b4e6a4c3 100644 --- a/translations/id.json +++ b/translations/id.json @@ -35,9 +35,9 @@ "MODULE_ERROR_MALFORMED_URL": "URL tidak valid.", "MODULE_ERROR_NO_CONNECTION": "Tidak ada koneksi internet.", "MODULE_ERROR_UNAUTHORIZED": "Gagal otentikasi.", - "MODULE_ERROR_RATE_LIMITED": "Too many requests. Retrying later.", - "MODULE_ERROR_SERVER_ERROR": "Server error. Retrying later.", - "MODULE_ERROR_CLIENT_ERROR": "Request failed.", + "MODULE_ERROR_RATE_LIMITED": "Terlalu banyak permintaan. Mencoba lagi nanti.", + "MODULE_ERROR_SERVER_ERROR": "Kesalahan server. Mencoba lagi nanti.", + "MODULE_ERROR_CLIENT_ERROR": "Permintaan gagal.", "MODULE_ERROR_UNSPECIFIED": "Silakan periksa log untuk informasi lebih lanjut.", "NEWSFEED_NO_ITEMS": "Saat ini tidak ada berita.", diff --git a/translations/is.json b/translations/is.json index a3f1b203ed..3ca35da4c4 100644 --- a/translations/is.json +++ b/translations/is.json @@ -36,9 +36,9 @@ "MODULE_ERROR_MALFORMED_URL": "Villa í slóð.", "MODULE_ERROR_NO_CONNECTION": "Engin nettenging.", "MODULE_ERROR_UNAUTHORIZED": "Auðkenning mistókst.", - "MODULE_ERROR_RATE_LIMITED": "Too many requests. Retrying later.", - "MODULE_ERROR_SERVER_ERROR": "Server error. Retrying later.", - "MODULE_ERROR_CLIENT_ERROR": "Request failed.", + "MODULE_ERROR_RATE_LIMITED": "Of margar beiðnir. Reyni aftur síðar.", + "MODULE_ERROR_SERVER_ERROR": "Villa í þjóni. Reyni aftur síðar.", + "MODULE_ERROR_CLIENT_ERROR": "Beiðni mistókst.", "MODULE_ERROR_UNSPECIFIED": "Vinsamlegast athugaðu skráningu fyrir frekari upplýsingar.", "NEWSFEED_NO_ITEMS": "Engar fréttir í boði núna.", diff --git a/translations/it.json b/translations/it.json index 687c6a0b1d..d8ca1f990f 100644 --- a/translations/it.json +++ b/translations/it.json @@ -35,9 +35,9 @@ "MODULE_ERROR_MALFORMED_URL": "URL non valido.", "MODULE_ERROR_NO_CONNECTION": "Nessuna connessione a Internet.", "MODULE_ERROR_UNAUTHORIZED": "Autenticazione non riuscita.", - "MODULE_ERROR_RATE_LIMITED": "Too many requests. Retrying later.", - "MODULE_ERROR_SERVER_ERROR": "Server error. Retrying later.", - "MODULE_ERROR_CLIENT_ERROR": "Request failed.", + "MODULE_ERROR_RATE_LIMITED": "Troppe richieste. Riprovo più tardi.", + "MODULE_ERROR_SERVER_ERROR": "Errore del server. Riprovo più tardi.", + "MODULE_ERROR_CLIENT_ERROR": "Richiesta fallita.", "MODULE_ERROR_UNSPECIFIED": "Si prega di controllare i log per ulteriori dettagli.", "NEWSFEED_NO_ITEMS": "Al momento non ci sono notizie.", diff --git a/translations/ja.json b/translations/ja.json index 6a22788f89..2ec19581c9 100644 --- a/translations/ja.json +++ b/translations/ja.json @@ -36,9 +36,9 @@ "MODULE_ERROR_MALFORMED_URL": "不正なURLです。", "MODULE_ERROR_NO_CONNECTION": "インターネット接続がありません。", "MODULE_ERROR_UNAUTHORIZED": "認証に失敗しました。", - "MODULE_ERROR_RATE_LIMITED": "Too many requests. Retrying later.", - "MODULE_ERROR_SERVER_ERROR": "Server error. Retrying later.", - "MODULE_ERROR_CLIENT_ERROR": "Request failed.", + "MODULE_ERROR_RATE_LIMITED": "リクエストが多すぎます。後で再試行します。", + "MODULE_ERROR_SERVER_ERROR": "サーバーエラー。後で再試行します。", + "MODULE_ERROR_CLIENT_ERROR": "リクエストが失敗しました。", "MODULE_ERROR_UNSPECIFIED": "詳細はログを確認してください。", "NEWSFEED_NO_ITEMS": "現在ニュースはありません。", diff --git a/translations/ko.json b/translations/ko.json index b59af38c6f..c5d223e817 100644 --- a/translations/ko.json +++ b/translations/ko.json @@ -36,9 +36,9 @@ "MODULE_ERROR_MALFORMED_URL": "잘못된 URL 형식입니다.", "MODULE_ERROR_NO_CONNECTION": "인터넷이 연결되지 않았습니다.", "MODULE_ERROR_UNAUTHORIZED": "인증이 실패했습니다.", - "MODULE_ERROR_RATE_LIMITED": "Too many requests. Retrying later.", - "MODULE_ERROR_SERVER_ERROR": "Server error. Retrying later.", - "MODULE_ERROR_CLIENT_ERROR": "Request failed.", + "MODULE_ERROR_RATE_LIMITED": "요청이 너무 많습니다. 나중에 다시 시도합니다.", + "MODULE_ERROR_SERVER_ERROR": "서버 오류. 나중에 다시 시도합니다.", + "MODULE_ERROR_CLIENT_ERROR": "요청 실패.", "MODULE_ERROR_UNSPECIFIED": "상세 내용은 로그를 확인하세요.", "NEWSFEED_NO_ITEMS": "현재 뉴스가 없습니다.", diff --git a/translations/lt.json b/translations/lt.json index 429513c254..75ed4d8979 100644 --- a/translations/lt.json +++ b/translations/lt.json @@ -36,9 +36,9 @@ "MODULE_ERROR_MALFORMED_URL": "Netinkama URL nuoroda.", "MODULE_ERROR_NO_CONNECTION": "Nėra interneto ryšio.", "MODULE_ERROR_UNAUTHORIZED": "Autorizacija nepavyko.", - "MODULE_ERROR_RATE_LIMITED": "Too many requests. Retrying later.", - "MODULE_ERROR_SERVER_ERROR": "Server error. Retrying later.", - "MODULE_ERROR_CLIENT_ERROR": "Request failed.", + "MODULE_ERROR_RATE_LIMITED": "Per daug užklausų. Bandoma vėl vėliau.", + "MODULE_ERROR_SERVER_ERROR": "Serverio klaida. Bandoma vėl vėliau.", + "MODULE_ERROR_CLIENT_ERROR": "Užklausa nepavyko.", "MODULE_ERROR_UNSPECIFIED": "Patikrinkite žurnalus, kad gautumėte daugiau informacijos.", "NEWSFEED_NO_ITEMS": "Šiuo metu naujienų nėra.", diff --git a/translations/ms-my.json b/translations/ms-my.json index 9f8b5b21cc..54e0bffc52 100644 --- a/translations/ms-my.json +++ b/translations/ms-my.json @@ -36,9 +36,9 @@ "MODULE_ERROR_MALFORMED_URL": "URL tidak sah.", "MODULE_ERROR_NO_CONNECTION": "Tiada sambungan internet.", "MODULE_ERROR_UNAUTHORIZED": "Kebenaran gagal.", - "MODULE_ERROR_RATE_LIMITED": "Too many requests. Retrying later.", - "MODULE_ERROR_SERVER_ERROR": "Server error. Retrying later.", - "MODULE_ERROR_CLIENT_ERROR": "Request failed.", + "MODULE_ERROR_RATE_LIMITED": "Terlalu banyak permintaan. Cuba lagi nanti.", + "MODULE_ERROR_SERVER_ERROR": "Ralat pelayan. Cuba lagi nanti.", + "MODULE_ERROR_CLIENT_ERROR": "Permintaan gagal.", "MODULE_ERROR_UNSPECIFIED": "Sila semak log untuk maklumat lanjut.", "NEWSFEED_NO_ITEMS": "Tiada berita buat masa ini.", diff --git a/translations/nb.json b/translations/nb.json index 007620f1b3..3dd5f20983 100644 --- a/translations/nb.json +++ b/translations/nb.json @@ -36,9 +36,9 @@ "MODULE_ERROR_MALFORMED_URL": "Ugyldig URL.", "MODULE_ERROR_NO_CONNECTION": "Ingen internettforbindelse.", "MODULE_ERROR_UNAUTHORIZED": "Autentisering mislyktes.", - "MODULE_ERROR_RATE_LIMITED": "Too many requests. Retrying later.", - "MODULE_ERROR_SERVER_ERROR": "Server error. Retrying later.", - "MODULE_ERROR_CLIENT_ERROR": "Request failed.", + "MODULE_ERROR_RATE_LIMITED": "For mange forespørsler. Prøver igjen senere.", + "MODULE_ERROR_SERVER_ERROR": "Serverfeil. Prøver igjen senere.", + "MODULE_ERROR_CLIENT_ERROR": "Forespørselen mislyktes.", "MODULE_ERROR_UNSPECIFIED": "Vennligst sjekk loggene for mer informasjon.", "NEWSFEED_NO_ITEMS": "Ingen nyheter tilgjengelig for øyeblikket.", diff --git a/translations/nl.json b/translations/nl.json index 419922298f..e4f8a77585 100644 --- a/translations/nl.json +++ b/translations/nl.json @@ -36,9 +36,9 @@ "MODULE_ERROR_MALFORMED_URL": "Ongeldige url.", "MODULE_ERROR_NO_CONNECTION": "Geen internet verbinding.", "MODULE_ERROR_UNAUTHORIZED": "Authenticatie mislukt.", - "MODULE_ERROR_RATE_LIMITED": "Too many requests. Retrying later.", - "MODULE_ERROR_SERVER_ERROR": "Server error. Retrying later.", - "MODULE_ERROR_CLIENT_ERROR": "Request failed.", + "MODULE_ERROR_RATE_LIMITED": "Te veel verzoeken. Later opnieuw proberen.", + "MODULE_ERROR_SERVER_ERROR": "Serverfout. Later opnieuw proberen.", + "MODULE_ERROR_CLIENT_ERROR": "Verzoek mislukt.", "MODULE_ERROR_UNSPECIFIED": "Bekijk de logs voor meer informatie.", "NEWSFEED_NO_ITEMS": "Geen nieuws op dit moment.", diff --git a/translations/nn.json b/translations/nn.json index 8b0a6164d4..833f3c3df8 100644 --- a/translations/nn.json +++ b/translations/nn.json @@ -36,9 +36,9 @@ "MODULE_ERROR_MALFORMED_URL": "Ugyldig URL.", "MODULE_ERROR_NO_CONNECTION": "Ingen internettforbindelse.", "MODULE_ERROR_UNAUTHORIZED": "Autentisering mislyktes.", - "MODULE_ERROR_RATE_LIMITED": "Too many requests. Retrying later.", - "MODULE_ERROR_SERVER_ERROR": "Server error. Retrying later.", - "MODULE_ERROR_CLIENT_ERROR": "Request failed.", + "MODULE_ERROR_RATE_LIMITED": "For mange førespurnader. Prøvar igjen seinare.", + "MODULE_ERROR_SERVER_ERROR": "Serverfeil. Prøvar igjen seinare.", + "MODULE_ERROR_CLIENT_ERROR": "Førespurnaden feila.", "MODULE_ERROR_UNSPECIFIED": "Vennligst sjekk loggfilene for meir informasjon.", "NEWSFEED_NO_ITEMS": "Ingen nyhende tilgjengeleg no.", diff --git a/translations/pl.json b/translations/pl.json index 2659283842..545c8fe9e5 100644 --- a/translations/pl.json +++ b/translations/pl.json @@ -36,9 +36,9 @@ "MODULE_ERROR_MALFORMED_URL": "Nieprawidłowy adres URL.", "MODULE_ERROR_NO_CONNECTION": "Brak połączenia z internetem.", "MODULE_ERROR_UNAUTHORIZED": "Autoryzacja nie powiodła się.", - "MODULE_ERROR_RATE_LIMITED": "Too many requests. Retrying later.", - "MODULE_ERROR_SERVER_ERROR": "Server error. Retrying later.", - "MODULE_ERROR_CLIENT_ERROR": "Request failed.", + "MODULE_ERROR_RATE_LIMITED": "Zbyt wiele żądań. Ponowna próba później.", + "MODULE_ERROR_SERVER_ERROR": "Błąd serwera. Ponowna próba później.", + "MODULE_ERROR_CLIENT_ERROR": "Żądanie nie powiodło się.", "MODULE_ERROR_UNSPECIFIED": "Sprawdź logi, aby uzyskać więcej informacji.", "NEWSFEED_NO_ITEMS": "Brak wiadomości w tej chwili.", diff --git a/translations/pt-br.json b/translations/pt-br.json index 3fd5db07c2..6c59fec9ab 100644 --- a/translations/pt-br.json +++ b/translations/pt-br.json @@ -35,9 +35,9 @@ "MODULE_ERROR_MALFORMED_URL": "URL inválido.", "MODULE_ERROR_NO_CONNECTION": "Sem conexão com a Internet.", "MODULE_ERROR_UNAUTHORIZED": "Falha na autenticação.", - "MODULE_ERROR_RATE_LIMITED": "Too many requests. Retrying later.", - "MODULE_ERROR_SERVER_ERROR": "Server error. Retrying later.", - "MODULE_ERROR_CLIENT_ERROR": "Request failed.", + "MODULE_ERROR_RATE_LIMITED": "Muitas requisições. Tentando novamente mais tarde.", + "MODULE_ERROR_SERVER_ERROR": "Erro do servidor. Tentando novamente mais tarde.", + "MODULE_ERROR_CLIENT_ERROR": "Requisição falhou.", "MODULE_ERROR_UNSPECIFIED": "Verifique os logs para mais detalhes.", "NEWSFEED_NO_ITEMS": "Atualmente não há notícias.", diff --git a/translations/pt.json b/translations/pt.json index 9d931aadc0..b0aa6abac3 100644 --- a/translations/pt.json +++ b/translations/pt.json @@ -37,9 +37,9 @@ "MODULE_ERROR_MALFORMED_URL": "URL inválido.", "MODULE_ERROR_NO_CONNECTION": "Sem ligação à internet.", "MODULE_ERROR_UNAUTHORIZED": "Falha na autorização.", - "MODULE_ERROR_RATE_LIMITED": "Too many requests. Retrying later.", - "MODULE_ERROR_SERVER_ERROR": "Server error. Retrying later.", - "MODULE_ERROR_CLIENT_ERROR": "Request failed.", + "MODULE_ERROR_RATE_LIMITED": "Demasiados pedidos. A tentar novamente mais tarde.", + "MODULE_ERROR_SERVER_ERROR": "Erro do servidor. A tentar novamente mais tarde.", + "MODULE_ERROR_CLIENT_ERROR": "Pedido falhou.", "MODULE_ERROR_UNSPECIFIED": "Consulta os registos para mais detalhes.", "NEWSFEED_NO_ITEMS": "Sem notícias de momento.", diff --git a/translations/ro.json b/translations/ro.json index 86ca0d4d99..4d0422f1f2 100644 --- a/translations/ro.json +++ b/translations/ro.json @@ -36,9 +36,9 @@ "MODULE_ERROR_MALFORMED_URL": "URL incorect.", "MODULE_ERROR_NO_CONNECTION": "Fără conexiune la internet.", "MODULE_ERROR_UNAUTHORIZED": "Autorizarea a eșuat.", - "MODULE_ERROR_RATE_LIMITED": "Too many requests. Retrying later.", - "MODULE_ERROR_SERVER_ERROR": "Server error. Retrying later.", - "MODULE_ERROR_CLIENT_ERROR": "Request failed.", + "MODULE_ERROR_RATE_LIMITED": "Prea multe cereri. Se reîncearcă mai târziu.", + "MODULE_ERROR_SERVER_ERROR": "Eroare de server. Se reîncearcă mai târziu.", + "MODULE_ERROR_CLIENT_ERROR": "Cererea a eșuat.", "MODULE_ERROR_UNSPECIFIED": "Verificați jurnalele pentru mai multe detalii.", "NEWSFEED_NO_ITEMS": "Nu există știri în acest moment.", diff --git a/translations/ru.json b/translations/ru.json index c8c550a0ca..6620f1bcde 100644 --- a/translations/ru.json +++ b/translations/ru.json @@ -36,9 +36,9 @@ "MODULE_ERROR_MALFORMED_URL": "Неверный URL.", "MODULE_ERROR_NO_CONNECTION": "Нет интернет-соединения.", "MODULE_ERROR_UNAUTHORIZED": "Не удалось авторизоваться.", - "MODULE_ERROR_RATE_LIMITED": "Too many requests. Retrying later.", - "MODULE_ERROR_SERVER_ERROR": "Server error. Retrying later.", - "MODULE_ERROR_CLIENT_ERROR": "Request failed.", + "MODULE_ERROR_RATE_LIMITED": "Слишком много запросов. Повторная попытка позже.", + "MODULE_ERROR_SERVER_ERROR": "Ошибка сервера. Повторная попытка позже.", + "MODULE_ERROR_CLIENT_ERROR": "Запрос не удался.", "MODULE_ERROR_UNSPECIFIED": "Пожалуйста, проверьте логи для получения дополнительной информации.", "NEWSFEED_NO_ITEMS": "В данный момент нет новостей.", diff --git a/translations/sk.json b/translations/sk.json index 1217a94b6f..2407126eb8 100644 --- a/translations/sk.json +++ b/translations/sk.json @@ -36,9 +36,9 @@ "MODULE_ERROR_MALFORMED_URL": "Nesprávna URL adresa.", "MODULE_ERROR_NO_CONNECTION": "Nie je pripojenie k internetu.", "MODULE_ERROR_UNAUTHORIZED": "Autorizácia zlyhala.", - "MODULE_ERROR_RATE_LIMITED": "Too many requests. Retrying later.", - "MODULE_ERROR_SERVER_ERROR": "Server error. Retrying later.", - "MODULE_ERROR_CLIENT_ERROR": "Request failed.", + "MODULE_ERROR_RATE_LIMITED": "Príliš veľa požiadaviek. Skúšam znovu neskôr.", + "MODULE_ERROR_SERVER_ERROR": "Chyba servera. Skúšam znovu neskôr.", + "MODULE_ERROR_CLIENT_ERROR": "Požiadavka zlyhala.", "MODULE_ERROR_UNSPECIFIED": "Skontrolujte protokoly pre viac informácií.", "NEWSFEED_NO_ITEMS": "Momentálne žiadne správy.", diff --git a/translations/sv.json b/translations/sv.json index 5f98105d4b..0add5c4360 100644 --- a/translations/sv.json +++ b/translations/sv.json @@ -36,9 +36,9 @@ "MODULE_ERROR_MALFORMED_URL": "Felaktig URL.", "MODULE_ERROR_NO_CONNECTION": "Ingen internetanslutning.", "MODULE_ERROR_UNAUTHORIZED": "Autentisering misslyckades.", - "MODULE_ERROR_RATE_LIMITED": "Too many requests. Retrying later.", - "MODULE_ERROR_SERVER_ERROR": "Server error. Retrying later.", - "MODULE_ERROR_CLIENT_ERROR": "Request failed.", + "MODULE_ERROR_RATE_LIMITED": "För många förfrågningar. Försöker igen senare.", + "MODULE_ERROR_SERVER_ERROR": "Serverfel. Försöker igen senare.", + "MODULE_ERROR_CLIENT_ERROR": "Förfrågan misslyckades.", "MODULE_ERROR_UNSPECIFIED": "Vänligen kontrollera loggarna för mer information.", "NEWSFEED_NO_ITEMS": "Inga nyheter för tillfället.", diff --git a/translations/th.json b/translations/th.json index 2a1dfbd2ec..dfa120f33f 100644 --- a/translations/th.json +++ b/translations/th.json @@ -36,9 +36,9 @@ "MODULE_ERROR_MALFORMED_URL": "URL ผิดรูปแบบ", "MODULE_ERROR_NO_CONNECTION": "ไม่มีการเชื่อมต่ออินเทอร์เน็ต.", "MODULE_ERROR_UNAUTHORIZED": "การอนุญาตล้มเหลว", - "MODULE_ERROR_RATE_LIMITED": "Too many requests. Retrying later.", - "MODULE_ERROR_SERVER_ERROR": "Server error. Retrying later.", - "MODULE_ERROR_CLIENT_ERROR": "Request failed.", + "MODULE_ERROR_RATE_LIMITED": "คำขอมากเกินไป กำลังลองใหม่ในภายหลัง", + "MODULE_ERROR_SERVER_ERROR": "ข้อผิดพลาดเซิร์ฟเวอร์ กำลังลองใหม่ในภายหลัง", + "MODULE_ERROR_CLIENT_ERROR": "คำขอล้มเหลว", "MODULE_ERROR_UNSPECIFIED": "ตรวจสอบบันทึกสำหรับรายละเอียดเพิ่มเติม", "NEWSFEED_NO_ITEMS": "ไม่มีข่าวในขณะนี้", diff --git a/translations/tlh.json b/translations/tlh.json index a6813c8c72..b7a70a4368 100644 --- a/translations/tlh.json +++ b/translations/tlh.json @@ -36,9 +36,9 @@ "MODULE_ERROR_MALFORMED_URL": "URL ghobe' yImev.", "MODULE_ERROR_NO_CONNECTION": "Internet ghobe' yImev.", "MODULE_ERROR_UNAUTHORIZED": "ghobe' yImev.", - "MODULE_ERROR_RATE_LIMITED": "Too many requests. Retrying later.", - "MODULE_ERROR_SERVER_ERROR": "Server error. Retrying later.", - "MODULE_ERROR_CLIENT_ERROR": "Request failed.", + "MODULE_ERROR_RATE_LIMITED": "tlhoy rurqu' lut. vaj ratlh.", + "MODULE_ERROR_SERVER_ERROR": "Qagh server. vaj ratlh.", + "MODULE_ERROR_CLIENT_ERROR": "lut Qagh.", "MODULE_ERROR_UNSPECIFIED": "logmeyDaq yImev.", "NEWSFEED_NO_ITEMS": "DaHghachmey ghobe' yImev.", diff --git a/translations/tr.json b/translations/tr.json index 5e044277f8..6e0d3ad249 100644 --- a/translations/tr.json +++ b/translations/tr.json @@ -35,9 +35,9 @@ "MODULE_ERROR_MALFORMED_URL": "Hatalı URL.", "MODULE_ERROR_NO_CONNECTION": "İnternet bağlantısı yok.", "MODULE_ERROR_UNAUTHORIZED": "Yetkilendirme başarısız.", - "MODULE_ERROR_RATE_LIMITED": "Too many requests. Retrying later.", - "MODULE_ERROR_SERVER_ERROR": "Server error. Retrying later.", - "MODULE_ERROR_CLIENT_ERROR": "Request failed.", + "MODULE_ERROR_RATE_LIMITED": "Çok fazla istek. Daha sonra yeniden deneniyor.", + "MODULE_ERROR_SERVER_ERROR": "Sunucu hatası. Daha sonra yeniden deneniyor.", + "MODULE_ERROR_CLIENT_ERROR": "İstek başarısız oldu.", "MODULE_ERROR_UNSPECIFIED": "Daha fazla ayrıntı için günlükleri kontrol edin.", "NEWSFEED_NO_ITEMS": "Şu anda haber yok.", diff --git a/translations/uk.json b/translations/uk.json index 35d4c665e3..ffc308226a 100644 --- a/translations/uk.json +++ b/translations/uk.json @@ -36,9 +36,9 @@ "MODULE_ERROR_MALFORMED_URL": "Неправильний URL.", "MODULE_ERROR_NO_CONNECTION": "Немає підключення до Інтернету.", "MODULE_ERROR_UNAUTHORIZED": "Авторизація не вдалася.", - "MODULE_ERROR_RATE_LIMITED": "Too many requests. Retrying later.", - "MODULE_ERROR_SERVER_ERROR": "Server error. Retrying later.", - "MODULE_ERROR_CLIENT_ERROR": "Request failed.", + "MODULE_ERROR_RATE_LIMITED": "Забагато запитів. Повторна спроба пізніше.", + "MODULE_ERROR_SERVER_ERROR": "Помилка сервера. Повторна спроба пізніше.", + "MODULE_ERROR_CLIENT_ERROR": "Запит не вдався.", "MODULE_ERROR_UNSPECIFIED": "Перевірте журнали для отримання додаткової інформації.", "NEWSFEED_NO_ITEMS": "Немає новин на даний момент.", diff --git a/translations/zh-cn.json b/translations/zh-cn.json index 94ddb45b3f..7e1cf7ca65 100644 --- a/translations/zh-cn.json +++ b/translations/zh-cn.json @@ -36,9 +36,9 @@ "MODULE_ERROR_MALFORMED_URL": "URL格式错误。", "MODULE_ERROR_NO_CONNECTION": "无网络连接。", "MODULE_ERROR_UNAUTHORIZED": "授权失败。", - "MODULE_ERROR_RATE_LIMITED": "Too many requests. Retrying later.", - "MODULE_ERROR_SERVER_ERROR": "Server error. Retrying later.", - "MODULE_ERROR_CLIENT_ERROR": "Request failed.", + "MODULE_ERROR_RATE_LIMITED": "请求过多。稍后重试。", + "MODULE_ERROR_SERVER_ERROR": "服务器错误。稍后重试。", + "MODULE_ERROR_CLIENT_ERROR": "请求失败。", "MODULE_ERROR_UNSPECIFIED": "请查看日志以获取更多详细信息。", "NEWSFEED_NO_ITEMS": "目前没有新闻。", diff --git a/translations/zh-tw.json b/translations/zh-tw.json index f1e3d2c1e0..13c4edab90 100644 --- a/translations/zh-tw.json +++ b/translations/zh-tw.json @@ -36,9 +36,9 @@ "MODULE_ERROR_MALFORMED_URL": "網址格式錯誤。", "MODULE_ERROR_NO_CONNECTION": "無網路連線。", "MODULE_ERROR_UNAUTHORIZED": "授權失敗。", - "MODULE_ERROR_RATE_LIMITED": "Too many requests. Retrying later.", - "MODULE_ERROR_SERVER_ERROR": "Server error. Retrying later.", - "MODULE_ERROR_CLIENT_ERROR": "Request failed.", + "MODULE_ERROR_RATE_LIMITED": "請求過多。稍後重試。", + "MODULE_ERROR_SERVER_ERROR": "伺服器錯誤。稍後重試。", + "MODULE_ERROR_CLIENT_ERROR": "請求失敗。", "MODULE_ERROR_UNSPECIFIED": "查看日誌以了解詳情。", "NEWSFEED_NO_ITEMS": "目前沒有新聞。", From 4c19d2cea45d60ab3d1c078543b818cc0dec7845 Mon Sep 17 00:00:00 2001 From: Kristjan ESPERANTO <35647502+KristjanESPERANTO@users.noreply.github.com> Date: Wed, 21 Jan 2026 11:06:54 +0100 Subject: [PATCH 3/3] fix: remove duplicates from pt translation --- translations/pt.json | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/translations/pt.json b/translations/pt.json index b0aa6abac3..3c1f26bde4 100644 --- a/translations/pt.json +++ b/translations/pt.json @@ -44,16 +44,6 @@ "NEWSFEED_NO_ITEMS": "Sem notícias de momento.", - "UPDATE_NOTIFICATION": "Está disponível uma atualização do MagicMirror².", - "UPDATE_NOTIFICATION_MODULE": "Atualização disponível para o módulo {MODULE_NAME}.", - "UPDATE_INFO_SINGLE": "A instalação atual está {COMMIT_COUNT} commit atrás na ramificação {BRANCH_NAME}.", - "UPDATE_INFO_MULTIPLE": "A instalação atual está {COMMIT_COUNT} commits atrás na ramificação {BRANCH_NAME}.", - "UPDATE_NOTIFICATION_DONE": "Atualização concluída do módulo {MODULE_NAME}.", - "UPDATE_NOTIFICATION_ERROR": "Erro na atualização do módulo {MODULE_NAME}.", - "UPDATE_NOTIFICATION_NEED-RESTART": "É necessário reiniciar o MagicMirror.", - - "MODULE_ERROR_MALFORMED_URL": "URL Inválido.", - "UPDATE_NOTIFICATION": "Está disponível uma atualização do MagicMirror².", "UPDATE_NOTIFICATION_MODULE": "Atualização disponível para o módulo {MODULE_NAME}.", "UPDATE_INFO_SINGLE": "A instalação atual está {COMMIT_COUNT} commit atrás na ramificação {BRANCH_NAME}.",